{
  "openapi": "3.1.0",
  "info": {
    "title": "CartaFlow API",
    "version": "1.0.0",
    "summary": "Automated physical mail to any address in Brazil.",
    "description": "The CartaFlow API prints, envelopes and posts letters through Correios to any address in Brazil, as simple or registered mail, and verifies physical addresses with a letter that carries a code. Every request uses JSON and an API key in the Authorization header.",
    "contact": {
      "name": "CartaFlow",
      "url": "https://www.cartaflow.com.br"
    }
  },
  "servers": [
    {
      "url": "https://api.cartaflow.com.br/v1",
      "description": "CartaFlow API."
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "letters",
      "x-displayName": "Letters",
      "description": "Send PDFs to be printed and posted, follow their status and calculate the price."
    },
    {
      "name": "uploads",
      "x-displayName": "PDF uploads",
      "description": "Send large PDFs, up to 10 MB, in two steps, before creating the letter."
    },
    {
      "name": "verifications",
      "x-displayName": "Address verifications",
      "description": "Confirm that a person receives mail at the address they gave you."
    },
    {
      "name": "postal_codes",
      "x-displayName": "Postal codes",
      "description": "Look up the address of a postal code (CEP)."
    },
    {
      "name": "account",
      "x-displayName": "Account and balance",
      "description": "Account details, balance and transactions."
    },
    {
      "name": "events",
      "x-displayName": "Events",
      "description": "Events from the last 30 days."
    },
    {
      "name": "webhooks",
      "x-displayName": "Webhooks",
      "description": "What CartaFlow sends to your server."
    }
  ],
  "paths": {
    "/letters": {
      "post": {
        "operationId": "createLetter",
        "tags": [
          "letters"
        ],
        "summary": "Create a letter",
        "description": "Sends a document to be printed and posted. CartaFlow checks the address and the document, debits the price from your balance and returns the letter with status `received`. If something is wrong, nothing is created or charged, and the 422 response lists every problem at once.\n\nSend the PDF in one of these ways:\n\n| Way | How | PDF up to |\n| --- | --- | --- |\n| File in the request | multipart/form-data, with the PDF in the `file` field and the other fields with it | 4 MB |\n| By URL | JSON, `document.type: url`: we download the PDF right away | 10 MB |\n| Two-step upload | POST /v1/uploads, PUT the file to its `upload_url`, then JSON with `document.type: upload` | 10 MB |\n| Base64 | JSON, `document.type: base64`: the PDF inside the JSON | 3 MB |\n\nThe request body is limited to 4.5 MB. For PDFs larger than 4 MB, use a URL or the two-step upload.\n\nTo upload the file together with the data, switch the body format to multipart/form-data:\n\n```bash\ncurl https://api.cartaflow.com.br/v1/letters \\\n  -H \"Authorization: Bearer $CARTAFLOW_API_KEY\" \\\n  -F \"file=@fatura-outubro.pdf\" \\\n  -F \"to[name]=Destinatário Exemplo\" \\\n  -F \"to[postal_code]=01001-000\" \\\n  -F \"to[number]=128\" \\\n  -F \"color=true\"\n```\n\nA PDF can also carry markers such as `{{name}}`: send the values in `variables` and we write each one in place of its marker.\n\nIn the address, only `name`, `postal_code` and `number` are required: when you leave the rest out, it is filled in from the postal code.\n\nTo send a registered letter (\"carta registrada\"), with a Correios tracking code, send `postal_services` with `registered`. The return receipt (`return_receipt`) and restricted delivery (`restricted_delivery`) go on top of registration. Each service costs extra.\n\nTo schedule, send `send_date`. A scheduled letter is validated now, stays `scheduled` and is only charged on its send date, when the balance must cover the price.\n\nAlways send the `Idempotency-Key` header, for example with the invoice id. If the connection drops and you repeat the call, the API returns the same letter instead of creating a second one.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Two formats with the same fields: **application/json**, with the PDF in `document` (URL, two-step upload or base64), or **multipart/form-data**, with the PDF file in the `file` field (up to 4 MB). Switch the format with the selector on the box below.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLetterRequest"
              },
              "examples": {
                "pdf_url": {
                  "summary": "PDF from a URL",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
                    },
                    "color": true,
                    "reference": "fatura-2026-10-0042",
                    "metadata": {
                      "customer_id": "1842"
                    }
                  }
                },
                "pdf_upload": {
                  "summary": "PDF sent with POST /v1/uploads",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "upload",
                      "upload_id": "upl_6Np3Vx8Rk2Tq"
                    },
                    "reference": "fatura-2026-10-0042"
                  }
                },
                "registered": {
                  "summary": "Registered letter with return receipt",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "upload",
                      "upload_id": "upl_2Hc7Tm4Zq9Lw"
                    },
                    "postal_services": [
                      "registered",
                      "return_receipt"
                    ],
                    "reference": "contrato-5531"
                  }
                },
                "pdf_base64": {
                  "summary": "PDF in base64",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "base64",
                      "data": "JVBERi0xLjcKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFI..."
                    },
                    "double_sided": true,
                    "reference": "contrato-5531"
                  }
                },
                "scheduled": {
                  "summary": "Scheduled for a date",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/lembretes/revisao-2291.pdf"
                    },
                    "send_date": "2026-10-20",
                    "reference": "lembrete-revisao-2291"
                  }
                },
                "full_address": {
                  "summary": "Full address",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "street": "Praça da Sé",
                      "number": "128",
                      "complement": "Ap. 52",
                      "neighborhood": "Sé",
                      "city": "São Paulo",
                      "state": "SP",
                      "postal_code": "01001-000"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
                    },
                    "color": true,
                    "reference": "fatura-2026-10-0042"
                  }
                },
                "pdf_variables": {
                  "summary": "PDF with variables",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/cobrancas/aviso-cobranca.pdf",
                      "variables": {
                        "nome": "Destinatário Exemplo",
                        "valor": "R$ 189,90",
                        "vencimento": "20/10/2026"
                      }
                    },
                    "reference": "cobranca-8841"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CreateLetterUpload"
              },
              "example": {
                "file": "fatura-outubro.pdf",
                "to": {
                  "name": "Destinatário Exemplo",
                  "postal_code": "01001-000",
                  "number": "128",
                  "complement": "Ap. 52"
                },
                "color": true,
                "reference": "fatura-2026-10-0042"
              },
              "encoding": {
                "file": {
                  "contentType": "application/pdf"
                },
                "to": {
                  "style": "deepObject",
                  "explode": true
                },
                "from": {
                  "style": "deepObject",
                  "explode": true
                },
                "variables": {
                  "style": "deepObject",
                  "explode": true
                },
                "metadata": {
                  "style": "deepObject",
                  "explode": true
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The letter was created. Status `received` (already charged) or `scheduled` (scheduled, charged on its send date).",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                },
                "examples": {
                  "received": {
                    "summary": "Sent right away",
                    "value": {
                      "id": "ltr_8Kq2wX4mN7pR",
                      "object": "letter",
                      "status": "received",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "url",
                        "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                        "variables": null
                      },
                      "color": true,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [],
                      "pages": 2,
                      "sheets": 2,
                      "price": {
                        "currency": "BRL",
                        "total": 1135,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "additional_sheets",
                            "quantity": 1,
                            "unit_amount": 75,
                            "amount": 75
                          },
                          {
                            "type": "color",
                            "quantity": 2,
                            "unit_amount": 35,
                            "amount": 70
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                      "reference": "fatura-2026-10-0042",
                      "metadata": {
                        "customer_id": "1842"
                      },
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": null,
                        "printed_at": null,
                        "posted_at": null,
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "registered": {
                    "summary": "Registered letter with return receipt",
                    "value": {
                      "id": "ltr_3Wb6Jn9Pd4Ys",
                      "object": "letter",
                      "status": "received",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "upload",
                        "filename": "notificacao-contrato-5531.pdf",
                        "variables": null
                      },
                      "color": false,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [
                        "registered",
                        "return_receipt"
                      ],
                      "pages": 1,
                      "sheets": 1,
                      "price": {
                        "currency": "BRL",
                        "total": 3340,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "registered",
                            "quantity": 1,
                            "unit_amount": 1175,
                            "amount": 1175
                          },
                          {
                            "type": "return_receipt",
                            "quantity": 1,
                            "unit_amount": 1175,
                            "amount": 1175
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_3Wb6Jn9Pd4Ys.pdf?expires=1760369400&signature=7e3b90a4",
                      "reference": "contrato-5531",
                      "metadata": {},
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": null,
                        "printed_at": null,
                        "posted_at": null,
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "scheduled": {
                    "summary": "Scheduled",
                    "value": {
                      "id": "ltr_5Mz8Tc1Wq6Nv",
                      "object": "letter",
                      "status": "scheduled",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "url",
                        "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                        "variables": null
                      },
                      "color": true,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [],
                      "pages": 2,
                      "sheets": 2,
                      "price": {
                        "currency": "BRL",
                        "total": 1135,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "additional_sheets",
                            "quantity": 1,
                            "unit_amount": 75,
                            "amount": 75
                          },
                          {
                            "type": "color",
                            "quantity": 2,
                            "unit_amount": 35,
                            "amount": 70
                          }
                        ]
                      },
                      "send_date": "2026-10-20",
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                      "reference": "lembrete-revisao-2291",
                      "metadata": {},
                      "status_transitions": {
                        "received_at": null,
                        "in_production_at": null,
                        "printed_at": null,
                        "posted_at": null,
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "The balance does not cover the price of a letter sent right away. Nothing was created. Letters scheduled with `send_date` do not need balance at creation.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "billing_error",
                    "code": "insufficient_balance",
                    "message": "The available balance (R$ 4.10) does not cover this mailing (R$ 11.35). Top up your balance in the dashboard.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#insufficient_balance",
                    "details": null
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "422": {
            "description": "One or more fields have problems. Nothing was created or charged.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "3 fields have problems. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "to.postal_code",
                        "code": "postal_code_not_found",
                        "message": "We could not find postal code 01001-999. Check the 8 digits."
                      },
                      {
                        "param": "document.url",
                        "code": "address_area_not_blank",
                        "message": "There is content in the address area of the first page. Leave the area blank or use address_placement: extra_page."
                      },
                      {
                        "param": "postal_services",
                        "code": "requires_registered",
                        "message": "return_receipt only works with registered. Add registered to postal_services."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "operationId": "listLetters",
        "tags": [
          "letters"
        ],
        "summary": "List letters",
        "description": "Returns the account’s letters, newest first, one page at a time. Use the filters to find, for example, every letter posted in October, the ones that failed or the letter for one invoice.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "scheduled",
                "received",
                "in_production",
                "printed",
                "posted",
                "canceled",
                "failed"
              ],
              "description": "Only items in this status.\n\n**Possible values**\n\n- `scheduled`: The letter was validated and is waiting for its `send_date`. It has not been charged yet. On that date, at 06:00 Brasília time, CartaFlow debits the balance and the letter moves to `received`. If the balance does not cover the price, it moves to `canceled`. It can be canceled at no cost.\n- `received`: CartaFlow validated the document and the address, charged the letter to your balance and put it in the production queue. It can still be canceled, and the amount goes back to the balance.\n- `in_production`: The letter is part of a print batch. From this point on it can no longer be canceled.\n- `printed`: The letter was printed, folded and put in its envelope. Posting is the next step.\n- `posted`: The letter was handed to Correios, the Brazilian postal service. From here on delivery follows the postal service, and CartaFlow receives no further updates about it. A registered letter carries its Correios tracking code in `tracking_code`.\n- `canceled`: The letter was canceled before production and nothing was printed. `cancellation_reason` says why: you canceled it, or the balance did not cover a scheduled letter on its send date. If it had been charged, the amount went back to the balance.\n- `failed`: Something went wrong in production and the letter will not be posted. `failure_reason` says why. The amount went back to the balance automatically.",
              "x-enumDescriptions": {
                "scheduled": "The letter was validated and is waiting for its `send_date`. It has not been charged yet. On that date, at 06:00 Brasília time, CartaFlow debits the balance and the letter moves to `received`. If the balance does not cover the price, it moves to `canceled`. It can be canceled at no cost.",
                "received": "CartaFlow validated the document and the address, charged the letter to your balance and put it in the production queue. It can still be canceled, and the amount goes back to the balance.",
                "in_production": "The letter is part of a print batch. From this point on it can no longer be canceled.",
                "printed": "The letter was printed, folded and put in its envelope. Posting is the next step.",
                "posted": "The letter was handed to Correios, the Brazilian postal service. From here on delivery follows the postal service, and CartaFlow receives no further updates about it. A registered letter carries its Correios tracking code in `tracking_code`.",
                "canceled": "The letter was canceled before production and nothing was printed. `cancellation_reason` says why: you canceled it, or the balance did not cover a scheduled letter on its send date. If it had been charged, the amount went back to the balance.",
                "failed": "Something went wrong in production and the letter will not be posted. `failure_reason` says why. The amount went back to the balance automatically."
              }
            },
            "description": "Only items in this status."
          },
          {
            "$ref": "#/components/parameters/Reference"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of letters.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LetterList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "ltr_8Kq2wX4mN7pR",
                      "object": "letter",
                      "status": "posted",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "url",
                        "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                        "variables": null
                      },
                      "color": true,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [],
                      "pages": 2,
                      "sheets": 2,
                      "price": {
                        "currency": "BRL",
                        "total": 1135,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "additional_sheets",
                            "quantity": 1,
                            "unit_amount": 75,
                            "amount": 75
                          },
                          {
                            "type": "color",
                            "quantity": 2,
                            "unit_amount": 35,
                            "amount": 70
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                      "reference": "fatura-2026-10-0042",
                      "metadata": {
                        "customer_id": "1842"
                      },
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "printed_at": "2026-10-14T10:42:00Z",
                        "posted_at": "2026-10-14T16:05:00Z",
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "A filter has an invalid value.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "One field has a problem. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "status",
                        "code": "invalid_value",
                        "message": "Use one of these values: scheduled, received, in_production, printed, posted, canceled, failed."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/letters/{letter_id}": {
      "get": {
        "operationId": "getLetter",
        "tags": [
          "letters"
        ],
        "summary": "Retrieve a letter",
        "description": "Returns the letter with its current status and a fresh link to the PDF in `preview_url`. To follow many letters, prefer webhooks over polling.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LetterId"
          }
        ],
        "responses": {
          "200": {
            "description": "The letter.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                },
                "examples": {
                  "posted": {
                    "summary": "Posted",
                    "value": {
                      "id": "ltr_8Kq2wX4mN7pR",
                      "object": "letter",
                      "status": "posted",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "url",
                        "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                        "variables": null
                      },
                      "color": true,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [],
                      "pages": 2,
                      "sheets": 2,
                      "price": {
                        "currency": "BRL",
                        "total": 1135,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "additional_sheets",
                            "quantity": 1,
                            "unit_amount": 75,
                            "amount": 75
                          },
                          {
                            "type": "color",
                            "quantity": 2,
                            "unit_amount": 35,
                            "amount": 70
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                      "reference": "fatura-2026-10-0042",
                      "metadata": {
                        "customer_id": "1842"
                      },
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "printed_at": "2026-10-14T10:42:00Z",
                        "posted_at": "2026-10-14T16:05:00Z",
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "registered": {
                    "summary": "Registered letter, posted, with tracking code",
                    "value": {
                      "id": "ltr_3Wb6Jn9Pd4Ys",
                      "object": "letter",
                      "status": "posted",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "upload",
                        "filename": "notificacao-contrato-5531.pdf",
                        "variables": null
                      },
                      "color": false,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [
                        "registered",
                        "return_receipt"
                      ],
                      "pages": 1,
                      "sheets": 1,
                      "price": {
                        "currency": "BRL",
                        "total": 3340,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "registered",
                            "quantity": 1,
                            "unit_amount": 1175,
                            "amount": 1175
                          },
                          {
                            "type": "return_receipt",
                            "quantity": 1,
                            "unit_amount": 1175,
                            "amount": 1175
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": null,
                      "tracking_code": "RA123456785BR",
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_3Wb6Jn9Pd4Ys.pdf?expires=1760369400&signature=7e3b90a4",
                      "reference": "contrato-5531",
                      "metadata": {},
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "printed_at": "2026-10-14T10:42:00Z",
                        "posted_at": "2026-10-14T16:05:00Z",
                        "canceled_at": null,
                        "failed_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "failed": {
                    "summary": "Failed in production",
                    "value": {
                      "id": "ltr_8Kq2wX4mN7pR",
                      "object": "letter",
                      "status": "failed",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "from": {
                        "name": "Exemplo Serviços Ltda.",
                        "street": "Avenida Exemplo",
                        "number": "1000",
                        "complement": "Sala 301",
                        "neighborhood": "Bela Vista",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01310-100"
                      },
                      "document": {
                        "type": "url",
                        "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                        "variables": null
                      },
                      "color": true,
                      "double_sided": false,
                      "address_placement": "first_page",
                      "postal_services": [],
                      "pages": 2,
                      "sheets": 2,
                      "price": {
                        "currency": "BRL",
                        "total": 1135,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "additional_sheets",
                            "quantity": 1,
                            "unit_amount": 75,
                            "amount": 75
                          },
                          {
                            "type": "color",
                            "quantity": 2,
                            "unit_amount": 35,
                            "amount": 70
                          }
                        ]
                      },
                      "send_date": null,
                      "cancellation_reason": null,
                      "failure_reason": "damaged_in_production",
                      "tracking_code": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                      "reference": "fatura-2026-10-0042",
                      "metadata": {
                        "customer_id": "1842"
                      },
                      "status_transitions": {
                        "received_at": "2026-10-13T14:20:00Z",
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "printed_at": null,
                        "posted_at": null,
                        "canceled_at": null,
                        "failed_at": "2026-10-14T11:30:00Z"
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/letters/{letter_id}/cancel": {
      "post": {
        "operationId": "cancelLetter",
        "tags": [
          "letters"
        ],
        "summary": "Cancel a letter",
        "description": "Cancels a letter that is `scheduled` or `received`. Nothing is printed. If it had been charged, the amount goes back to the balance right away; if it was scheduled, nothing had been charged. Once the letter is in production (or if it failed), the API answers 409 with `letter_not_cancelable`. Canceling a letter that is already canceled returns the same letter, with no error.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LetterId"
          }
        ],
        "responses": {
          "200": {
            "description": "The canceled letter.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                },
                "example": {
                  "id": "ltr_8Kq2wX4mN7pR",
                  "object": "letter",
                  "status": "canceled",
                  "to": {
                    "name": "Destinatário Exemplo",
                    "street": "Praça da Sé",
                    "number": "128",
                    "complement": "Ap. 52",
                    "neighborhood": "Sé",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01001-000"
                  },
                  "from": {
                    "name": "Exemplo Serviços Ltda.",
                    "street": "Avenida Exemplo",
                    "number": "1000",
                    "complement": "Sala 301",
                    "neighborhood": "Bela Vista",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01310-100"
                  },
                  "document": {
                    "type": "url",
                    "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                    "variables": null
                  },
                  "color": true,
                  "double_sided": false,
                  "address_placement": "first_page",
                  "postal_services": [],
                  "pages": 2,
                  "sheets": 2,
                  "price": {
                    "currency": "BRL",
                    "total": 1135,
                    "items": [
                      {
                        "type": "base",
                        "quantity": 1,
                        "unit_amount": 990,
                        "amount": 990
                      },
                      {
                        "type": "additional_sheets",
                        "quantity": 1,
                        "unit_amount": 75,
                        "amount": 75
                      },
                      {
                        "type": "color",
                        "quantity": 2,
                        "unit_amount": 35,
                        "amount": 70
                      }
                    ]
                  },
                  "send_date": null,
                  "cancellation_reason": "requested",
                  "failure_reason": null,
                  "tracking_code": null,
                  "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                  "reference": "fatura-2026-10-0042",
                  "metadata": {
                    "customer_id": "1842"
                  },
                  "status_transitions": {
                    "received_at": "2026-10-13T14:20:00Z",
                    "in_production_at": null,
                    "printed_at": null,
                    "posted_at": null,
                    "canceled_at": "2026-10-13T14:31:00Z",
                    "failed_at": null
                  },
                  "created_at": "2026-10-13T14:20:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The letter is already in production and cannot be canceled.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "conflict_error",
                    "code": "letter_not_cancelable",
                    "message": "The letter is in_production and can no longer be canceled.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#letter_not_cancelable",
                    "details": null
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/letters/quote": {
      "post": {
        "operationId": "createQuote",
        "tags": [
          "letters"
        ],
        "summary": "Calculate the price",
        "description": "Simulates a letter without creating it. The body is exactly the same as for POST /v1/letters, in JSON or in multipart/form-data with the file: the API validates everything, completes the address from the postal code, counts the pages of the document and returns the price on the account’s current plan, including the Correios services chosen in `postal_services`. Nothing is created, charged or stored, and the balance does not need to cover the amount. An upload used in a dry run (`document.type: upload`) stays available for creating the letter.\n\nUse it to show the price to your user before sending, to check the complete address or to check a document at no cost. If the dry run passes, creating the letter with the same body passes too, as long as there is balance.",
        "requestBody": {
          "required": true,
          "description": "Two formats with the same fields: **application/json**, with the PDF in `document` (URL, two-step upload or base64), or **multipart/form-data**, with the PDF file in the `file` field (up to 4 MB). Switch the format with the selector on the box below.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLetterRequest"
              },
              "examples": {
                "pdf_url": {
                  "summary": "PDF from a URL",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
                    },
                    "color": true
                  }
                },
                "registered": {
                  "summary": "Registered letter with return receipt",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "document": {
                      "type": "upload",
                      "upload_id": "upl_6Np3Vx8Rk2Tq"
                    },
                    "postal_services": [
                      "registered",
                      "return_receipt"
                    ]
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/CreateLetterUpload"
              },
              "example": {
                "file": "fatura-outubro.pdf",
                "to": {
                  "name": "Destinatário Exemplo",
                  "postal_code": "01001-000",
                  "number": "128",
                  "complement": "Ap. 52"
                },
                "color": true,
                "reference": "fatura-2026-10-0042"
              },
              "encoding": {
                "file": {
                  "contentType": "application/pdf"
                },
                "to": {
                  "style": "deepObject",
                  "explode": true
                },
                "from": {
                  "style": "deepObject",
                  "explode": true
                },
                "variables": {
                  "style": "deepObject",
                  "explode": true
                },
                "metadata": {
                  "style": "deepObject",
                  "explode": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The price and the complete address.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                },
                "example": {
                  "object": "quote",
                  "plan": "essential",
                  "to": {
                    "name": "Destinatário Exemplo",
                    "street": "Praça da Sé",
                    "number": "128",
                    "complement": "Ap. 52",
                    "neighborhood": "Sé",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01001-000"
                  },
                  "pages": 2,
                  "sheets": 2,
                  "price": {
                    "currency": "BRL",
                    "total": 1135,
                    "items": [
                      {
                        "type": "base",
                        "quantity": 1,
                        "unit_amount": 990,
                        "amount": 990
                      },
                      {
                        "type": "additional_sheets",
                        "quantity": 1,
                        "unit_amount": 75,
                        "amount": 75
                      },
                      {
                        "type": "color",
                        "quantity": 2,
                        "unit_amount": 35,
                        "amount": 70
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "413": {
            "$ref": "#/components/responses/RequestTooLarge"
          },
          "422": {
            "description": "The body has the same problems it would have at creation.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "One field has a problem. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "document.url",
                        "code": "too_many_sheets",
                        "message": "The document has 9 pages, which would take 9 sheets. The maximum is 6. Use double_sided: true."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/uploads": {
      "post": {
        "operationId": "createUpload",
        "tags": [
          "uploads"
        ],
        "summary": "Create an upload",
        "description": "First step to send a large PDF, up to 10 MB, that does not fit in one request (the body is limited to 4.5 MB, so multipart takes PDFs of up to 4 MB). It works in three steps:\n\n1. Call this endpoint with the file name and size. The response carries the upload `id` and a signed `upload_url`.\n2. Send the PDF bytes with a `PUT` to the `upload_url`, with the `Content-Type: application/pdf` header and **no** `Authorization` header: the signature is already in the URL. The link works for 2 hours.\n3. Create the letter with `document: { \"type\": \"upload\", \"upload_id\": \"upl_...\" }`, within 24 hours.\n\n```bash\ncurl -X PUT \"$UPLOAD_URL\" \\\n  -H \"Content-Type: application/pdf\" \\\n  --data-binary \"@fatura-outubro.pdf\"\n```\n\nThe file is checked when the letter is created, with the same rules as any PDF (A4, no password, address area). Each upload belongs to your account and is good for one letter only: a second letter with the same `upload_id` gets a 422 with `upload_already_used`. A dry run with POST /v1/letters/quote does not use it up.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUploadRequest"
              },
              "example": {
                "filename": "fatura-outubro.pdf",
                "size": 7340032
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The upload was created. Send the file to `upload_url` within 2 hours.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upload"
                },
                "example": {
                  "id": "upl_6Np3Vx8Rk2Tq",
                  "object": "upload",
                  "filename": "fatura-outubro.pdf",
                  "size": 7340032,
                  "upload_url": "https://files.cartaflow.com.br/uploads/upl_6Np3Vx8Rk2Tq?token=4f8a2c91d7",
                  "upload_url_expires_at": "2026-10-13T16:20:00Z",
                  "expires_at": "2026-10-14T14:20:00Z",
                  "created_at": "2026-10-13T14:20:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "422": {
            "description": "One or more fields have problems. Nothing was created.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "One field has a problem. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "size",
                        "code": "out_of_range",
                        "message": "The file can be up to 10485760 bytes (10 MB)."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/verifications": {
      "post": {
        "operationId": "createVerification",
        "tags": [
          "verifications"
        ],
        "summary": "Create a verification",
        "description": "Mails a letter with your brand and a 6-digit code to the address. When the person confirms the code, the verification moves to `verified` and you receive the `verification.verified` event. The price is debited from your balance at creation.\n\nPick how the person confirms with `method`:\n\n- `hosted_page`: they scan the QR code, or open the printed address and type the code, on a page with your brand, hosted by CartaFlow.\n- `code`: they type the code into your website or app, and your server checks it with POST /v1/verifications/{verification_id}/check.\n\nThe letter can be made in two ways:\n\n| Way | How | Price |\n| --- | --- | --- |\n| CartaFlow letter template (default) | No `document`. Customize the title, text, footer, QR code and page address in `letter`; whatever you leave out comes from your company’s default letter, saved in the dashboard. | One base mailing |\n| Your own PDF | `document` with `url`, `upload` or `base64`. The PDF must have the `{{OTP_CODE}}` marker and can have `{{VERIFICATION_URL}}` and `{{QR_CODE}}`. Takes `color`, `double_sided` and `address_placement`. | That of a letter with the same options |\n\nThis endpoint only takes JSON. To send your PDF as a file, use the two-step upload (POST /v1/uploads).\n\nThe code never appears in the API or in the dashboard: it only exists on the letter CartaFlow prints. `preview_url` shows the letter with the code hidden (`000 000`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVerificationRequest"
              },
              "examples": {
                "hosted_page": {
                  "summary": "Hosted page, default letter",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "method": "hosted_page",
                    "return_url": "https://www.exemplo.com.br/conta",
                    "reference": "cliente-1842"
                  }
                },
                "letter": {
                  "summary": "Customized CartaFlow letter template",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "method": "hosted_page",
                    "letter": {
                      "title": "Confirme seu endereço, {{nome}}",
                      "body": "{{empresa}} precisa confirmar o endereço do seu cadastro. Use o código abaixo.",
                      "include_page_url": false
                    },
                    "reference": "cliente-1842"
                  }
                },
                "code": {
                  "summary": "Code typed in your app",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "method": "code",
                    "instructions": "Abra o app, vá em Perfil > Endereço e digite o código.",
                    "reference": "cliente-1842"
                  }
                },
                "own_pdf": {
                  "summary": "Your own PDF, with {{OTP_CODE}}",
                  "value": {
                    "to": {
                      "name": "Destinatário Exemplo",
                      "postal_code": "01001-000",
                      "number": "128",
                      "complement": "Ap. 52"
                    },
                    "method": "hosted_page",
                    "document": {
                      "type": "upload",
                      "upload_id": "upl_6Np3Vx8Rk2Tq",
                      "variables": {
                        "nome": "Destinatário Exemplo"
                      }
                    },
                    "color": true,
                    "reference": "cliente-2210"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The verification was created and charged. Status `received`.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                },
                "examples": {
                  "template": {
                    "summary": "CartaFlow letter template",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "received",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": null,
                      "confirmation": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": null,
                        "awaiting_code_at": null,
                        "verified_at": null,
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "own_pdf": {
                    "summary": "Your own PDF",
                    "value": {
                      "id": "ver_5Tc7Gm1Xs9Hq",
                      "object": "verification",
                      "status": "received",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "upload",
                        "filename": "verificacao-endereco.pdf",
                        "variables": {
                          "nome": "Destinatário Exemplo"
                        }
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/4Fz8Np2Kw6Qr1Lt9Ds3Hm7",
                      "attempts_remaining": 5,
                      "expires_at": null,
                      "confirmation": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_5Tc7Gm1Xs9Hq.pdf?expires=1760369400&signature=c3f9d518",
                      "price": {
                        "currency": "BRL",
                        "total": 1025,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          },
                          {
                            "type": "color",
                            "quantity": 1,
                            "unit_amount": 35,
                            "amount": 35
                          }
                        ]
                      },
                      "reference": "cliente-2210",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": null,
                        "awaiting_code_at": null,
                        "verified_at": null,
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "422": {
            "description": "One or more fields have problems. Nothing was created or charged.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "2 fields have problems. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "to.street",
                        "code": "address_incomplete",
                        "message": "Postal code 13165-000 covers the whole city and has no street. Send street and neighborhood."
                      },
                      {
                        "param": "document.upload_id",
                        "code": "otp_code_missing",
                        "message": "The PDF needs the {{OTP_CODE}} marker, where we print the code."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "operationId": "listVerifications",
        "tags": [
          "verifications"
        ],
        "summary": "List verifications",
        "description": "Returns the account’s verifications, created through the API and the dashboard, newest first.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "received",
                "in_production",
                "awaiting_code",
                "verified",
                "failed",
                "expired",
                "canceled",
                "revoked"
              ],
              "description": "Only items in this status.\n\n**Possible values**\n\n- `received`: CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.\n- `in_production`: The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.\n- `awaiting_code`: The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.\n- `verified`: The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.\n- `failed`: 5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.\n- `expired`: 60 days went by after posting without the person confirming the code.\n- `canceled`: The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.\n- `revoked`: You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again.",
              "x-enumDescriptions": {
                "received": "CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.",
                "in_production": "The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.",
                "awaiting_code": "The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.",
                "verified": "The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.",
                "failed": "5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.",
                "expired": "60 days went by after posting without the person confirming the code.",
                "canceled": "The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.",
                "revoked": "You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again."
              }
            },
            "description": "Only items in this status."
          },
          {
            "$ref": "#/components/parameters/Reference"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of verifications.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "awaiting_code",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": null,
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/verifications/{verification_id}": {
      "get": {
        "operationId": "getVerification",
        "tags": [
          "verifications"
        ],
        "summary": "Retrieve a verification",
        "description": "Returns the verification with its current status and, once confirmed, how it was confirmed (`confirmation`). Each call returns a fresh `preview_url`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/VerificationId"
          }
        ],
        "responses": {
          "200": {
            "description": "The verification.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                },
                "examples": {
                  "awaiting_code": {
                    "summary": "Awaiting code",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "awaiting_code",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": null,
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "verified": {
                    "summary": "Verified on the page",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "verified",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": {
                        "method": "hosted_page",
                        "hosted_page_entry": "qr_code",
                        "confirmed_at": "2026-10-21T19:32:00Z",
                        "ip": "198.51.100.23",
                        "location": {
                          "city": "São Paulo",
                          "region": "SP",
                          "country": "BR",
                          "postal_code": "01000",
                          "latitude": -23.5475,
                          "longitude": -46.6361
                        },
                        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                        "device": {
                          "type": "mobile",
                          "os": {
                            "name": "iOS",
                            "version": "17.5"
                          },
                          "browser": {
                            "name": "Safari",
                            "version": "17.5"
                          }
                        },
                        "client": {
                          "language": "pt-BR",
                          "accept_language": "pt-BR,pt;q=0.9",
                          "timezone": "America/Sao_Paulo",
                          "screen": {
                            "width": 390,
                            "height": 844,
                            "pixel_ratio": 3
                          },
                          "time_on_page_ms": 8100
                        },
                        "precise_location": {
                          "latitude": -23.5489,
                          "longitude": -46.6388,
                          "accuracy_m": 14.5,
                          "distance_m": 606,
                          "shared_at": "2026-10-21T19:32:40Z",
                          "ip": "198.51.100.23",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                          "address_coordinates": {
                            "latitude": -23.5503898,
                            "longitude": -46.633081
                          }
                        }
                      },
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": "2026-10-21T19:32:00Z",
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "revoked": {
                    "summary": "Revoked after being verified",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "revoked",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": {
                        "method": "hosted_page",
                        "hosted_page_entry": "qr_code",
                        "confirmed_at": "2026-10-21T19:32:00Z",
                        "ip": "198.51.100.23",
                        "location": {
                          "city": "São Paulo",
                          "region": "SP",
                          "country": "BR",
                          "postal_code": "01000",
                          "latitude": -23.5475,
                          "longitude": -46.6361
                        },
                        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                        "device": {
                          "type": "mobile",
                          "os": {
                            "name": "iOS",
                            "version": "17.5"
                          },
                          "browser": {
                            "name": "Safari",
                            "version": "17.5"
                          }
                        },
                        "client": {
                          "language": "pt-BR",
                          "accept_language": "pt-BR,pt;q=0.9",
                          "timezone": "America/Sao_Paulo",
                          "screen": {
                            "width": 390,
                            "height": 844,
                            "pixel_ratio": 3
                          },
                          "time_on_page_ms": 8100
                        },
                        "precise_location": {
                          "latitude": -23.5489,
                          "longitude": -46.6388,
                          "accuracy_m": 14.5,
                          "distance_m": 606,
                          "shared_at": "2026-10-21T19:32:40Z",
                          "ip": "198.51.100.23",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                          "address_coordinates": {
                            "latitude": -23.5503898,
                            "longitude": -46.633081
                          }
                        }
                      },
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": "2026-10-21T19:32:00Z",
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": "2026-10-23T12:10:00Z"
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/verifications/{verification_id}/check": {
      "post": {
        "operationId": "checkVerification",
        "tags": [
          "verifications"
        ],
        "summary": "Check a code",
        "description": "Checks the code the person typed into your website or app. It works while the status is `awaiting_code`. Make the call from your server: a right code records the IP of the API caller in `confirmation`.\n\nA wrong code is not an API error: the response is 200 with `correct: false` and a lower `attempts_remaining`. After 5 wrong codes, counting those typed on the page, the verification moves to `failed`. Show the person how many attempts are left.\n\nA canceled or revoked verification no longer accepts codes: the response is 409.",
        "parameters": [
          {
            "$ref": "#/components/parameters/VerificationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckVerificationRequest"
              },
              "example": {
                "code": "482917"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The result of the check. See `correct`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationCheck"
                },
                "examples": {
                  "correct": {
                    "summary": "Right code",
                    "value": {
                      "object": "verification_check",
                      "correct": true,
                      "verification": {
                        "id": "ver_8Wn2Rt6Yk4Js",
                        "object": "verification",
                        "status": "verified",
                        "method": "code",
                        "source": "api",
                        "to": {
                          "name": "Destinatário Exemplo",
                          "street": "Praça da Sé",
                          "number": "128",
                          "complement": "Ap. 52",
                          "neighborhood": "Sé",
                          "city": "São Paulo",
                          "state": "SP",
                          "postal_code": "01001-000"
                        },
                        "document": {
                          "type": "template",
                          "title": "Confirme o seu endereço",
                          "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                          "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                          "include_qr_code": false,
                          "include_page_url": false
                        },
                        "instructions": "Abra o app, vá em Perfil > Endereço e digite o código.",
                        "return_url": null,
                        "hosted_page_url": null,
                        "attempts_remaining": 5,
                        "expires_at": "2026-12-14T16:05:00Z",
                        "confirmation": {
                          "method": "api",
                          "hosted_page_entry": null,
                          "confirmed_at": "2026-10-21T19:32:00Z",
                          "ip": "203.0.113.10",
                          "location": null,
                          "user_agent": "node",
                          "device": null,
                          "client": null,
                          "precise_location": null
                        },
                        "preview_url": "https://files.cartaflow.com.br/previews/ver_8Wn2Rt6Yk4Js.pdf?expires=1760369400&signature=a17c4e20",
                        "price": {
                          "currency": "BRL",
                          "total": 990,
                          "items": [
                            {
                              "type": "base",
                              "quantity": 1,
                              "unit_amount": 990,
                              "amount": 990
                            }
                          ]
                        },
                        "reference": "cliente-1842",
                        "metadata": {},
                        "status_transitions": {
                          "in_production_at": "2026-10-13T21:00:00Z",
                          "awaiting_code_at": "2026-10-15T16:05:00Z",
                          "verified_at": "2026-10-21T19:32:00Z",
                          "failed_at": null,
                          "expired_at": null,
                          "canceled_at": null,
                          "revoked_at": null
                        },
                        "created_at": "2026-10-13T14:20:00Z"
                      }
                    }
                  },
                  "wrong": {
                    "summary": "Wrong code",
                    "value": {
                      "object": "verification_check",
                      "correct": false,
                      "verification": {
                        "id": "ver_8Wn2Rt6Yk4Js",
                        "object": "verification",
                        "status": "awaiting_code",
                        "method": "code",
                        "source": "api",
                        "to": {
                          "name": "Destinatário Exemplo",
                          "street": "Praça da Sé",
                          "number": "128",
                          "complement": "Ap. 52",
                          "neighborhood": "Sé",
                          "city": "São Paulo",
                          "state": "SP",
                          "postal_code": "01001-000"
                        },
                        "document": {
                          "type": "template",
                          "title": "Confirme o seu endereço",
                          "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                          "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                          "include_qr_code": false,
                          "include_page_url": false
                        },
                        "instructions": "Abra o app, vá em Perfil > Endereço e digite o código.",
                        "return_url": null,
                        "hosted_page_url": null,
                        "attempts_remaining": 4,
                        "expires_at": "2026-12-14T16:05:00Z",
                        "confirmation": null,
                        "preview_url": "https://files.cartaflow.com.br/previews/ver_8Wn2Rt6Yk4Js.pdf?expires=1760369400&signature=a17c4e20",
                        "price": {
                          "currency": "BRL",
                          "total": 990,
                          "items": [
                            {
                              "type": "base",
                              "quantity": 1,
                              "unit_amount": 990,
                              "amount": 990
                            }
                          ]
                        },
                        "reference": "cliente-1842",
                        "metadata": {},
                        "status_transitions": {
                          "in_production_at": "2026-10-13T21:00:00Z",
                          "awaiting_code_at": "2026-10-15T16:05:00Z",
                          "verified_at": null,
                          "failed_at": null,
                          "expired_at": null,
                          "canceled_at": null,
                          "revoked_at": null
                        },
                        "created_at": "2026-10-13T14:20:00Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The verification is not waiting for a code: it was not posted yet, it is already finished, or it was canceled or revoked.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "conflict_error",
                    "code": "verification_not_awaiting_code",
                    "message": "The verification is not waiting for a code (current status: revoked).",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#verification_not_awaiting_code",
                    "details": null
                  }
                }
              }
            }
          },
          "422": {
            "description": "The code does not have 6 digits.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "One field has a problem. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "code",
                        "code": "invalid_format",
                        "message": "The code has 6 digits, numbers only."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/verifications/{verification_id}/cancel": {
      "post": {
        "operationId": "cancelVerification",
        "tags": [
          "verifications"
        ],
        "summary": "Cancel or revoke a verification",
        "description": "What happens depends on the status:\n\n| Status | Result | Amount |\n| --- | --- | --- |\n| `received` | `canceled`: nothing is printed. | Goes back to the balance. |\n| `in_production`, `awaiting_code` or `verified` | `revoked`: the code stops working, on the page and in the API, and the verification never shows as `verified` again. A letter that was already in production is still posted. | Does not go back. |\n| `canceled` or `revoked` | Nothing changes: the response carries the same verification, with no error. | |\n| `failed` or `expired` | 409 with `verification_not_cancelable`. | |\n\nRevoke when the address should no longer count as verified, for example when the account was closed or you suspect fraud. If the person opens the confirmation page after that, they see a notice telling them to contact your company.",
        "parameters": [
          {
            "$ref": "#/components/parameters/VerificationId"
          }
        ],
        "responses": {
          "200": {
            "description": "The canceled (`canceled`) or revoked (`revoked`) verification.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                },
                "examples": {
                  "canceled": {
                    "summary": "Canceled while received, refunded",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "canceled",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": null,
                      "confirmation": null,
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": null,
                        "awaiting_code_at": null,
                        "verified_at": null,
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": "2026-10-13T14:40:00Z",
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  },
                  "revoked": {
                    "summary": "Revoked after being verified, not refunded",
                    "value": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "revoked",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": {
                        "method": "hosted_page",
                        "hosted_page_entry": "qr_code",
                        "confirmed_at": "2026-10-21T19:32:00Z",
                        "ip": "198.51.100.23",
                        "location": {
                          "city": "São Paulo",
                          "region": "SP",
                          "country": "BR",
                          "postal_code": "01000",
                          "latitude": -23.5475,
                          "longitude": -46.6361
                        },
                        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                        "device": {
                          "type": "mobile",
                          "os": {
                            "name": "iOS",
                            "version": "17.5"
                          },
                          "browser": {
                            "name": "Safari",
                            "version": "17.5"
                          }
                        },
                        "client": {
                          "language": "pt-BR",
                          "accept_language": "pt-BR,pt;q=0.9",
                          "timezone": "America/Sao_Paulo",
                          "screen": {
                            "width": 390,
                            "height": 844,
                            "pixel_ratio": 3
                          },
                          "time_on_page_ms": 8100
                        },
                        "precise_location": {
                          "latitude": -23.5489,
                          "longitude": -46.6388,
                          "accuracy_m": 14.5,
                          "distance_m": 606,
                          "shared_at": "2026-10-21T19:32:40Z",
                          "ip": "198.51.100.23",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                          "address_coordinates": {
                            "latitude": -23.5503898,
                            "longitude": -46.633081
                          }
                        }
                      },
                      "preview_url": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3",
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": "2026-10-21T19:32:00Z",
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": "2026-10-23T12:10:00Z"
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The verification ended without a confirmation (`failed` or `expired`).",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "conflict_error",
                    "code": "verification_not_cancelable",
                    "message": "The verification is expired and cannot be canceled or revoked.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#verification_not_cancelable",
                    "details": null
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/postal-codes/{postal_code}": {
      "get": {
        "operationId": "getPostalCode",
        "tags": [
          "postal_codes"
        ],
        "summary": "Look up a postal code",
        "description": "Returns the street, neighborhood, city and state of a Brazilian postal code (CEP). It is the same lookup the API uses to complete letter addresses. Use it to fill in your customer’s address form from the postal code. Free of charge.",
        "parameters": [
          {
            "name": "postal_code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{5}-?[0-9]{3}$",
              "example": "01001-000"
            },
            "description": "The postal code, with or without the hyphen."
          }
        ],
        "responses": {
          "200": {
            "description": "The address of the postal code.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostalCode"
                },
                "example": {
                  "object": "postal_code",
                  "postal_code": "01001-000",
                  "street": "Praça da Sé",
                  "neighborhood": "Sé",
                  "city": "São Paulo",
                  "state": "SP"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "The postal code does not exist in the Correios database.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "not_found_error",
                    "code": "postal_code_not_found",
                    "message": "We could not find postal code 01001-999. Check the 8 digits.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#postal_code_not_found",
                    "details": null
                  }
                }
              }
            }
          },
          "422": {
            "description": "The postal code does not have 8 digits.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "type": "validation_error",
                    "code": "invalid_parameters",
                    "message": "One field has a problem. See details.",
                    "request_id": "req_9Vb4Xk2Lq8Mz",
                    "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_parameters",
                    "details": [
                      {
                        "param": "postal_code",
                        "code": "invalid_format",
                        "message": "The postal code has 8 digits, with or without the hyphen."
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/account": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "account"
        ],
        "summary": "Retrieve the account",
        "description": "Returns the account that owns the API key: company, CNPJ, plan and default sender. Useful to confirm which account a key belongs to, for example in integrations that serve many customers.",
        "responses": {
          "200": {
            "description": "The account.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "id": "acc_7Jw3Nf8Xq2Lp",
                  "object": "account",
                  "legal_name": "Exemplo Serviços Ltda.",
                  "trade_name": "Exemplo",
                  "cnpj": "12.345.678/0001-90",
                  "plan": "essential",
                  "default_sender": {
                    "name": "Exemplo Serviços Ltda.",
                    "street": "Avenida Exemplo",
                    "number": "1000",
                    "complement": "Sala 301",
                    "neighborhood": "Bela Vista",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01310-100"
                  },
                  "created_at": "2026-09-01T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/balance": {
      "get": {
        "operationId": "getBalance",
        "tags": [
          "account"
        ],
        "summary": "Retrieve the balance",
        "description": "Returns the balance available for new mailings. Check it before a large send: a letter is only created when the balance covers its price.",
        "responses": {
          "200": {
            "description": "The balance.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "object": "balance",
                  "currency": "BRL",
                  "available": 48865,
                  "pending": 0
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/balance/transactions": {
      "get": {
        "operationId": "listBalanceTransactions",
        "tags": [
          "account"
        ],
        "summary": "List balance transactions",
        "description": "Returns the movements in and out of the balance, newest first: top-ups, debits for letters and verifications, refunds for cancellations, credits and adjustments. Use it to reconcile the cost of each mailing.",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "top_up",
                "letter",
                "verification",
                "refund",
                "credit",
                "adjustment"
              ],
              "description": "Only transactions of this type.\n\n**Possible values**\n\n- `top_up`: Top-ups.\n- `letter`: Letter debits.\n- `verification`: Verification debits.\n- `refund`: Refunds for cancellations.\n- `credit`: Credits from CartaFlow.\n- `adjustment`: Adjustments by support.",
              "x-enumDescriptions": {
                "top_up": "Top-ups.",
                "letter": "Letter debits.",
                "verification": "Verification debits.",
                "refund": "Refunds for cancellations.",
                "credit": "Credits from CartaFlow.",
                "adjustment": "Adjustments by support."
              }
            },
            "description": "Only transactions of this type."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of transactions.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceTransactionList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "btx_4Lm8Qw2Zx9Kd",
                      "object": "balance_transaction",
                      "type": "letter",
                      "amount": -1135,
                      "currency": "BRL",
                      "balance_after": 48865,
                      "source_id": "ltr_8Kq2wX4mN7pR",
                      "description": null,
                      "created_at": "2026-10-13T14:20:00Z"
                    },
                    {
                      "id": "btx_1Gs5Vb7Nc3Pf",
                      "object": "balance_transaction",
                      "type": "top_up",
                      "amount": 50000,
                      "currency": "BRL",
                      "balance_after": 50000,
                      "source_id": null,
                      "description": null,
                      "created_at": "2026-10-12T11:02:00Z"
                    }
                  ],
                  "has_more": true,
                  "next_cursor": "eyJpZCI6ImJ0eF8xR3M1VmI3TmMzUGYifQ"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "events"
        ],
        "summary": "List events",
        "description": "Returns the events of the last 30 days, newest first. They are the same events webhooks deliver. Use it to recover events your server missed, for example during an outage, or to see the history of one object with `object_id`.",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "letter.scheduled",
                "letter.received",
                "letter.in_production",
                "letter.printed",
                "letter.posted",
                "letter.canceled",
                "letter.failed",
                "letter.updated",
                "verification.received",
                "verification.in_production",
                "verification.awaiting_code",
                "verification.verified",
                "verification.failed",
                "verification.expired",
                "verification.canceled",
                "verification.revoked"
              ],
              "description": "Only events of this type.\n\n**Possible values**\n\n- `letter.scheduled`: A letter was scheduled with `send_date`. It has not been charged yet.\n- `letter.received`: A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.\n- `letter.in_production`: The letter joined a print batch and can no longer be canceled.\n- `letter.printed`: The letter was printed and enveloped.\n- `letter.posted`: The letter was handed to Correios. It is the last event of a letter that was sent.\n- `letter.canceled`: The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.\n- `letter.failed`: The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.\n- `letter.updated`: The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount.\n- `verification.received`: A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.\n- `verification.in_production`: The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.\n- `verification.awaiting_code`: The letter with the code was posted. The person can confirm once it arrives.\n- `verification.verified`: The person confirmed the right code. The address is verified.\n- `verification.failed`: 5 wrong codes were entered and the verification was locked.\n- `verification.expired`: The person did not confirm the code within 60 days of posting.\n- `verification.canceled`: The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.\n- `verification.revoked`: You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified.",
              "x-enumDescriptions": {
                "letter.scheduled": "A letter was scheduled with `send_date`. It has not been charged yet.",
                "letter.received": "A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.",
                "letter.in_production": "The letter joined a print batch and can no longer be canceled.",
                "letter.printed": "The letter was printed and enveloped.",
                "letter.posted": "The letter was handed to Correios. It is the last event of a letter that was sent.",
                "letter.canceled": "The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.",
                "letter.failed": "The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.",
                "letter.updated": "The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount.",
                "verification.received": "A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.",
                "verification.in_production": "The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.",
                "verification.awaiting_code": "The letter with the code was posted. The person can confirm once it arrives.",
                "verification.verified": "The person confirmed the right code. The address is verified.",
                "verification.failed": "5 wrong codes were entered and the verification was locked.",
                "verification.expired": "The person did not confirm the code within 60 days of posting.",
                "verification.canceled": "The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.",
                "verification.revoked": "You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified."
              }
            },
            "description": "Only events of this type."
          },
          {
            "name": "object_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "ltr_8Kq2wX4mN7pR"
            },
            "description": "Only events of this object, such as a letter (`ltr_`) or a verification (`ver_`)."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "evt_6Tq1Yz8Wm3Rb",
                      "object": "event",
                      "type": "letter.posted",
                      "data": {
                        "id": "ltr_8Kq2wX4mN7pR",
                        "object": "letter",
                        "status": "posted",
                        "to": {
                          "name": "Destinatário Exemplo",
                          "street": "Praça da Sé",
                          "number": "128",
                          "complement": "Ap. 52",
                          "neighborhood": "Sé",
                          "city": "São Paulo",
                          "state": "SP",
                          "postal_code": "01001-000"
                        },
                        "from": {
                          "name": "Exemplo Serviços Ltda.",
                          "street": "Avenida Exemplo",
                          "number": "1000",
                          "complement": "Sala 301",
                          "neighborhood": "Bela Vista",
                          "city": "São Paulo",
                          "state": "SP",
                          "postal_code": "01310-100"
                        },
                        "document": {
                          "type": "url",
                          "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                          "variables": null
                        },
                        "color": true,
                        "double_sided": false,
                        "address_placement": "first_page",
                        "postal_services": [],
                        "pages": 2,
                        "sheets": 2,
                        "price": {
                          "currency": "BRL",
                          "total": 1135,
                          "items": [
                            {
                              "type": "base",
                              "quantity": 1,
                              "unit_amount": 990,
                              "amount": 990
                            },
                            {
                              "type": "additional_sheets",
                              "quantity": 1,
                              "unit_amount": 75,
                              "amount": 75
                            },
                            {
                              "type": "color",
                              "quantity": 2,
                              "unit_amount": 35,
                              "amount": 70
                            }
                          ]
                        },
                        "send_date": null,
                        "cancellation_reason": null,
                        "failure_reason": null,
                        "tracking_code": null,
                        "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                        "reference": "fatura-2026-10-0042",
                        "metadata": {
                          "customer_id": "1842"
                        },
                        "status_transitions": {
                          "received_at": "2026-10-13T14:20:00Z",
                          "in_production_at": "2026-10-13T21:00:00Z",
                          "printed_at": "2026-10-14T10:42:00Z",
                          "posted_at": "2026-10-14T16:05:00Z",
                          "canceled_at": null,
                          "failed_at": null
                        },
                        "created_at": "2026-10-13T14:20:00Z"
                      },
                      "created_at": "2026-10-14T16:05:00Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/events/{event_id}": {
      "get": {
        "operationId": "getEvent",
        "tags": [
          "events"
        ],
        "summary": "Retrieve an event",
        "description": "Returns one event. The object in `data` is a snapshot from the moment of the event, not the current state: retrieve the object by id for its current state.",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventId"
          }
        ],
        "responses": {
          "200": {
            "description": "The event.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                },
                "example": {
                  "id": "evt_6Tq1Yz8Wm3Rb",
                  "object": "event",
                  "type": "letter.posted",
                  "data": {
                    "id": "ltr_8Kq2wX4mN7pR",
                    "object": "letter",
                    "status": "posted",
                    "to": {
                      "name": "Destinatário Exemplo",
                      "street": "Praça da Sé",
                      "number": "128",
                      "complement": "Ap. 52",
                      "neighborhood": "Sé",
                      "city": "São Paulo",
                      "state": "SP",
                      "postal_code": "01001-000"
                    },
                    "from": {
                      "name": "Exemplo Serviços Ltda.",
                      "street": "Avenida Exemplo",
                      "number": "1000",
                      "complement": "Sala 301",
                      "neighborhood": "Bela Vista",
                      "city": "São Paulo",
                      "state": "SP",
                      "postal_code": "01310-100"
                    },
                    "document": {
                      "type": "url",
                      "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                      "variables": null
                    },
                    "color": true,
                    "double_sided": false,
                    "address_placement": "first_page",
                    "postal_services": [],
                    "pages": 2,
                    "sheets": 2,
                    "price": {
                      "currency": "BRL",
                      "total": 1135,
                      "items": [
                        {
                          "type": "base",
                          "quantity": 1,
                          "unit_amount": 990,
                          "amount": 990
                        },
                        {
                          "type": "additional_sheets",
                          "quantity": 1,
                          "unit_amount": 75,
                          "amount": 75
                        },
                        {
                          "type": "color",
                          "quantity": 2,
                          "unit_amount": 35,
                          "amount": 70
                        }
                      ]
                    },
                    "send_date": null,
                    "cancellation_reason": null,
                    "failure_reason": null,
                    "tracking_code": null,
                    "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                    "reference": "fatura-2026-10-0042",
                    "metadata": {
                      "customer_id": "1842"
                    },
                    "status_transitions": {
                      "received_at": "2026-10-13T14:20:00Z",
                      "in_production_at": "2026-10-13T21:00:00Z",
                      "printed_at": "2026-10-14T10:42:00Z",
                      "posted_at": "2026-10-14T16:05:00Z",
                      "canceled_at": null,
                      "failed_at": null
                    },
                    "created_at": "2026-10-13T14:20:00Z"
                  },
                  "created_at": "2026-10-14T16:05:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "webhooks": {
    "letter-events": {
      "post": {
        "operationId": "letterEvents",
        "tags": [
          "webhooks"
        ],
        "summary": "Letter events",
        "description": "CartaFlow POSTs to your webhook URL on every status change of a letter, and with `letter.updated` when it is changed in the dashboard before production, with the event in the body. `data` carries the full letter, so you do not need to call the API afterwards.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "evt_6Tq1Yz8Wm3Rb"
            },
            "description": "Event id. The same on every delivery attempt of an event: use it to ignore repeats."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1760457900"
            },
            "description": "Time of sending in Unix seconds. Reject deliveries more than 5 minutes away from your clock."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="
            },
            "description": "HMAC-SHA256 signature following the Standard Webhooks spec. Verify it before trusting the content; see the Webhooks guide."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  }
                ],
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "letter.scheduled",
                      "letter.received",
                      "letter.in_production",
                      "letter.printed",
                      "letter.posted",
                      "letter.canceled",
                      "letter.failed",
                      "letter.updated"
                    ],
                    "description": "The event type.\n\n**Possible values**\n\n- `letter.scheduled`: A letter was scheduled with `send_date`. It has not been charged yet.\n- `letter.received`: A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.\n- `letter.in_production`: The letter joined a print batch and can no longer be canceled.\n- `letter.printed`: The letter was printed and enveloped.\n- `letter.posted`: The letter was handed to Correios. It is the last event of a letter that was sent.\n- `letter.canceled`: The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.\n- `letter.failed`: The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.\n- `letter.updated`: The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount.",
                    "x-enumDescriptions": {
                      "letter.scheduled": "A letter was scheduled with `send_date`. It has not been charged yet.",
                      "letter.received": "A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.",
                      "letter.in_production": "The letter joined a print batch and can no longer be canceled.",
                      "letter.printed": "The letter was printed and enveloped.",
                      "letter.posted": "The letter was handed to Correios. It is the last event of a letter that was sent.",
                      "letter.canceled": "The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.",
                      "letter.failed": "The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.",
                      "letter.updated": "The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount."
                    }
                  },
                  "data": {
                    "$ref": "#/components/schemas/Letter"
                  }
                }
              },
              "example": {
                "id": "evt_6Tq1Yz8Wm3Rb",
                "object": "event",
                "type": "letter.posted",
                "data": {
                  "id": "ltr_8Kq2wX4mN7pR",
                  "object": "letter",
                  "status": "posted",
                  "to": {
                    "name": "Destinatário Exemplo",
                    "street": "Praça da Sé",
                    "number": "128",
                    "complement": "Ap. 52",
                    "neighborhood": "Sé",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01001-000"
                  },
                  "from": {
                    "name": "Exemplo Serviços Ltda.",
                    "street": "Avenida Exemplo",
                    "number": "1000",
                    "complement": "Sala 301",
                    "neighborhood": "Bela Vista",
                    "city": "São Paulo",
                    "state": "SP",
                    "postal_code": "01310-100"
                  },
                  "document": {
                    "type": "url",
                    "url": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf",
                    "variables": null
                  },
                  "color": true,
                  "double_sided": false,
                  "address_placement": "first_page",
                  "postal_services": [],
                  "pages": 2,
                  "sheets": 2,
                  "price": {
                    "currency": "BRL",
                    "total": 1135,
                    "items": [
                      {
                        "type": "base",
                        "quantity": 1,
                        "unit_amount": 990,
                        "amount": 990
                      },
                      {
                        "type": "additional_sheets",
                        "quantity": 1,
                        "unit_amount": 75,
                        "amount": 75
                      },
                      {
                        "type": "color",
                        "quantity": 2,
                        "unit_amount": 35,
                        "amount": 70
                      }
                    ]
                  },
                  "send_date": null,
                  "cancellation_reason": null,
                  "failure_reason": null,
                  "tracking_code": null,
                  "preview_url": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f2a7d",
                  "reference": "fatura-2026-10-0042",
                  "metadata": {
                    "customer_id": "1842"
                  },
                  "status_transitions": {
                    "received_at": "2026-10-13T14:20:00Z",
                    "in_production_at": "2026-10-13T21:00:00Z",
                    "printed_at": "2026-10-14T10:42:00Z",
                    "posted_at": "2026-10-14T16:05:00Z",
                    "canceled_at": null,
                    "failed_at": null
                  },
                  "created_at": "2026-10-13T14:20:00Z"
                },
                "created_at": "2026-10-14T16:05:00Z"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer with any 2xx status within 15 seconds to confirm receipt. Do slow work after answering."
          },
          "default": {
            "description": "Any other answer, or no answer in time, makes CartaFlow try again later."
          }
        }
      }
    },
    "verification-events": {
      "post": {
        "operationId": "verificationEvents",
        "tags": [
          "webhooks"
        ],
        "summary": "Verification events",
        "description": "CartaFlow POSTs to your webhook URL on every status change of a verification, created through the API or the dashboard. The key event is `verification.verified`: the address was confirmed, and `data.confirmation` says how. Also handle `verification.revoked`: a revoked verification, even one that was confirmed, no longer counts as verified. `data.preview_url` is `null`: retrieve the verification to get the link.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "evt_6Tq1Yz8Wm3Rb"
            },
            "description": "Event id. The same on every delivery attempt of an event: use it to ignore repeats."
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "1760457900"
            },
            "description": "Time of sending in Unix seconds. Reject deliveries more than 5 minutes away from your clock."
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="
            },
            "description": "HMAC-SHA256 signature following the Standard Webhooks spec. Verify it before trusting the content; see the Webhooks guide."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  }
                ],
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "verification.received",
                      "verification.in_production",
                      "verification.awaiting_code",
                      "verification.verified",
                      "verification.failed",
                      "verification.expired",
                      "verification.canceled",
                      "verification.revoked"
                    ],
                    "description": "The event type.\n\n**Possible values**\n\n- `verification.received`: A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.\n- `verification.in_production`: The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.\n- `verification.awaiting_code`: The letter with the code was posted. The person can confirm once it arrives.\n- `verification.verified`: The person confirmed the right code. The address is verified.\n- `verification.failed`: 5 wrong codes were entered and the verification was locked.\n- `verification.expired`: The person did not confirm the code within 60 days of posting.\n- `verification.canceled`: The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.\n- `verification.revoked`: You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified.",
                    "x-enumDescriptions": {
                      "verification.received": "A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.",
                      "verification.in_production": "The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.",
                      "verification.awaiting_code": "The letter with the code was posted. The person can confirm once it arrives.",
                      "verification.verified": "The person confirmed the right code. The address is verified.",
                      "verification.failed": "5 wrong codes were entered and the verification was locked.",
                      "verification.expired": "The person did not confirm the code within 60 days of posting.",
                      "verification.canceled": "The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.",
                      "verification.revoked": "You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified."
                    }
                  },
                  "data": {
                    "$ref": "#/components/schemas/Verification"
                  }
                }
              },
              "examples": {
                "verified": {
                  "summary": "Verified",
                  "value": {
                    "id": "evt_2Kp9Xc4Vn7Ld",
                    "object": "event",
                    "type": "verification.verified",
                    "data": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "verified",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": {
                        "method": "hosted_page",
                        "hosted_page_entry": "qr_code",
                        "confirmed_at": "2026-10-21T19:32:00Z",
                        "ip": "198.51.100.23",
                        "location": {
                          "city": "São Paulo",
                          "region": "SP",
                          "country": "BR",
                          "postal_code": "01000",
                          "latitude": -23.5475,
                          "longitude": -46.6361
                        },
                        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                        "device": {
                          "type": "mobile",
                          "os": {
                            "name": "iOS",
                            "version": "17.5"
                          },
                          "browser": {
                            "name": "Safari",
                            "version": "17.5"
                          }
                        },
                        "client": {
                          "language": "pt-BR",
                          "accept_language": "pt-BR,pt;q=0.9",
                          "timezone": "America/Sao_Paulo",
                          "screen": {
                            "width": 390,
                            "height": 844,
                            "pixel_ratio": 3
                          },
                          "time_on_page_ms": 8100
                        },
                        "precise_location": {
                          "latitude": -23.5489,
                          "longitude": -46.6388,
                          "accuracy_m": 14.5,
                          "distance_m": 606,
                          "shared_at": "2026-10-21T19:32:40Z",
                          "ip": "198.51.100.23",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                          "address_coordinates": {
                            "latitude": -23.5503898,
                            "longitude": -46.633081
                          }
                        }
                      },
                      "preview_url": null,
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": "2026-10-21T19:32:00Z",
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": null
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    },
                    "created_at": "2026-10-21T19:32:00Z"
                  }
                },
                "revoked": {
                  "summary": "Revoked",
                  "value": {
                    "id": "evt_9Rm3Hb6Tx1Wf",
                    "object": "event",
                    "type": "verification.revoked",
                    "data": {
                      "id": "ver_3Hd9Kp2qZ6tW",
                      "object": "verification",
                      "status": "revoked",
                      "method": "hosted_page",
                      "source": "api",
                      "to": {
                        "name": "Destinatário Exemplo",
                        "street": "Praça da Sé",
                        "number": "128",
                        "complement": "Ap. 52",
                        "neighborhood": "Sé",
                        "city": "São Paulo",
                        "state": "SP",
                        "postal_code": "01001-000"
                      },
                      "document": {
                        "type": "template",
                        "title": "Confirme o seu endereço",
                        "body": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
                        "footer": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
                        "include_qr_code": true,
                        "include_page_url": true
                      },
                      "instructions": null,
                      "return_url": "https://www.exemplo.com.br/conta",
                      "hosted_page_url": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1",
                      "attempts_remaining": 5,
                      "expires_at": "2026-12-14T16:05:00Z",
                      "confirmation": {
                        "method": "hosted_page",
                        "hosted_page_entry": "qr_code",
                        "confirmed_at": "2026-10-21T19:32:00Z",
                        "ip": "198.51.100.23",
                        "location": {
                          "city": "São Paulo",
                          "region": "SP",
                          "country": "BR",
                          "postal_code": "01000",
                          "latitude": -23.5475,
                          "longitude": -46.6361
                        },
                        "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                        "device": {
                          "type": "mobile",
                          "os": {
                            "name": "iOS",
                            "version": "17.5"
                          },
                          "browser": {
                            "name": "Safari",
                            "version": "17.5"
                          }
                        },
                        "client": {
                          "language": "pt-BR",
                          "accept_language": "pt-BR,pt;q=0.9",
                          "timezone": "America/Sao_Paulo",
                          "screen": {
                            "width": 390,
                            "height": 844,
                            "pixel_ratio": 3
                          },
                          "time_on_page_ms": 8100
                        },
                        "precise_location": {
                          "latitude": -23.5489,
                          "longitude": -46.6388,
                          "accuracy_m": 14.5,
                          "distance_m": 606,
                          "shared_at": "2026-10-21T19:32:40Z",
                          "ip": "198.51.100.23",
                          "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
                          "address_coordinates": {
                            "latitude": -23.5503898,
                            "longitude": -46.633081
                          }
                        }
                      },
                      "preview_url": null,
                      "price": {
                        "currency": "BRL",
                        "total": 990,
                        "items": [
                          {
                            "type": "base",
                            "quantity": 1,
                            "unit_amount": 990,
                            "amount": 990
                          }
                        ]
                      },
                      "reference": "cliente-1842",
                      "metadata": {},
                      "status_transitions": {
                        "in_production_at": "2026-10-13T21:00:00Z",
                        "awaiting_code_at": "2026-10-15T16:05:00Z",
                        "verified_at": "2026-10-21T19:32:00Z",
                        "failed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "revoked_at": "2026-10-23T12:10:00Z"
                      },
                      "created_at": "2026-10-13T14:20:00Z"
                    },
                    "created_at": "2026-10-23T12:10:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer with any 2xx status within 15 seconds to confirm receipt. Do slow work after answering."
          },
          "default": {
            "description": "Any other answer, or no answer in time, makes CartaFlow try again later."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key in the `Authorization: Bearer cf_live_...` header. Create and revoke keys in the dashboard, under Desenvolvedores > Chaves de API (Developers > API keys)."
      }
    },
    "schemas": {
      "AddressInput": {
        "type": "object",
        "title": "AddressInput",
        "description": "An address in Brazil. Only `name`, `postal_code` and `number` are required: fields you leave out are filled in from the postal code, and fields you send are used as you sent them. For example, with the postal code and the neighborhood, we use your neighborhood and look up the street, city and state from the postal code. If a field is missing and the postal code does not provide it, the API answers 422 with `address_incomplete` and nothing is created.",
        "required": [
          "name",
          "number",
          "postal_code"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
            "example": "Destinatário Exemplo"
          },
          "postal_code": {
            "type": "string",
            "pattern": "^[0-9]{5}-?[0-9]{3}$",
            "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
            "example": "01001-000"
          },
          "number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
            "example": "128"
          },
          "complement": {
            "type": "string",
            "maxLength": 60,
            "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
            "example": "Ap. 52"
          },
          "street": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
            "example": "Praça da Sé"
          },
          "neighborhood": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
            "example": "Sé"
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
            "example": "São Paulo"
          },
          "state": {
            "type": "string",
            "enum": [
              "AC",
              "AL",
              "AP",
              "AM",
              "BA",
              "CE",
              "DF",
              "ES",
              "GO",
              "MA",
              "MT",
              "MS",
              "MG",
              "PA",
              "PB",
              "PR",
              "PE",
              "PI",
              "RJ",
              "RN",
              "RS",
              "RO",
              "RR",
              "SC",
              "SP",
              "SE",
              "TO"
            ],
            "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
            "x-enumDescriptions": {
              "AC": "Acre",
              "AL": "Alagoas",
              "AP": "Amapá",
              "AM": "Amazonas",
              "BA": "Bahia",
              "CE": "Ceará",
              "DF": "Distrito Federal",
              "ES": "Espírito Santo",
              "GO": "Goiás",
              "MA": "Maranhão",
              "MT": "Mato Grosso",
              "MS": "Mato Grosso do Sul",
              "MG": "Minas Gerais",
              "PA": "Pará",
              "PB": "Paraíba",
              "PR": "Paraná",
              "PE": "Pernambuco",
              "PI": "Piauí",
              "RJ": "Rio de Janeiro",
              "RN": "Rio Grande do Norte",
              "RS": "Rio Grande do Sul",
              "RO": "Rondônia",
              "RR": "Roraima",
              "SC": "Santa Catarina",
              "SP": "São Paulo",
              "SE": "Sergipe",
              "TO": "Tocantins"
            },
            "example": "SP"
          }
        },
        "example": {
          "name": "Destinatário Exemplo",
          "postal_code": "01001-000",
          "number": "128",
          "complement": "Ap. 52"
        }
      },
      "Address": {
        "type": "object",
        "title": "Address",
        "description": "A complete address in Brazil, as CartaFlow prints it: the fields you sent plus the ones we filled in from the postal code.",
        "required": [
          "name",
          "street",
          "number",
          "complement",
          "neighborhood",
          "city",
          "state",
          "postal_code"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
            "example": "Destinatário Exemplo"
          },
          "street": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
            "example": "Praça da Sé"
          },
          "number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
            "example": "128"
          },
          "complement": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 60,
            "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
            "example": "Ap. 52"
          },
          "neighborhood": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
            "example": "Sé"
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "City. Up to 60 characters.",
            "example": "São Paulo"
          },
          "state": {
            "type": "string",
            "enum": [
              "AC",
              "AL",
              "AP",
              "AM",
              "BA",
              "CE",
              "DF",
              "ES",
              "GO",
              "MA",
              "MT",
              "MS",
              "MG",
              "PA",
              "PB",
              "PR",
              "PE",
              "PI",
              "RJ",
              "RN",
              "RS",
              "RO",
              "RR",
              "SC",
              "SP",
              "SE",
              "TO"
            ],
            "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
            "x-enumDescriptions": {
              "AC": "Acre",
              "AL": "Alagoas",
              "AP": "Amapá",
              "AM": "Amazonas",
              "BA": "Bahia",
              "CE": "Ceará",
              "DF": "Distrito Federal",
              "ES": "Espírito Santo",
              "GO": "Goiás",
              "MA": "Maranhão",
              "MT": "Mato Grosso",
              "MS": "Mato Grosso do Sul",
              "MG": "Minas Gerais",
              "PA": "Pará",
              "PB": "Paraíba",
              "PR": "Paraná",
              "PE": "Pernambuco",
              "PI": "Piauí",
              "RJ": "Rio de Janeiro",
              "RN": "Rio Grande do Norte",
              "RS": "Rio Grande do Sul",
              "RO": "Rondônia",
              "RR": "Roraima",
              "SC": "Santa Catarina",
              "SP": "São Paulo",
              "SE": "Sergipe",
              "TO": "Tocantins"
            },
            "example": "SP"
          },
          "postal_code": {
            "type": "string",
            "pattern": "^[0-9]{5}-[0-9]{3}$",
            "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
            "example": "01001-000"
          }
        }
      },
      "PriceItem": {
        "type": "object",
        "title": "PriceItem",
        "description": "One line of the price.",
        "required": [
          "type",
          "quantity",
          "unit_amount",
          "amount"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "base",
              "additional_sheets",
              "color",
              "registered",
              "return_receipt",
              "restricted_delivery"
            ],
            "description": "What this line charges for.\n\n**Possible values**\n\n- `base`: Base mailing, as a simple letter (\"carta simples\"): the first sheet printed in black and white, the envelope and postage. One per letter or verification.\n- `additional_sheets`: Sheets of the document beyond the first, charged per sheet. The address is never charged, even when `extra_page` adds a sheet. `quantity` is the number of additional sheets.\n- `color`: Color printing, charged per printed page: each printed side of a sheet counts as a page. `quantity` is the number of pages printed in color. The address side is never printed in color or charged.\n- `registered`: Registered letter, with a Correios tracking code. `quantity` is always 1.\n- `return_receipt`: Return receipt (AR). `quantity` is always 1.\n- `restricted_delivery`: Restricted delivery (MP). `quantity` is always 1.",
            "x-enumDescriptions": {
              "base": "Base mailing, as a simple letter (\"carta simples\"): the first sheet printed in black and white, the envelope and postage. One per letter or verification.",
              "additional_sheets": "Sheets of the document beyond the first, charged per sheet. The address is never charged, even when `extra_page` adds a sheet. `quantity` is the number of additional sheets.",
              "color": "Color printing, charged per printed page: each printed side of a sheet counts as a page. `quantity` is the number of pages printed in color. The address side is never printed in color or charged.",
              "registered": "Registered letter, with a Correios tracking code. `quantity` is always 1.",
              "return_receipt": "Return receipt (AR). `quantity` is always 1.",
              "restricted_delivery": "Restricted delivery (MP). `quantity` is always 1."
            }
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Quantity charged on this line.",
            "example": 1
          },
          "unit_amount": {
            "type": "integer",
            "description": "Price of one unit, according to the account plan. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 990
          },
          "amount": {
            "type": "integer",
            "description": "`quantity` times `unit_amount`. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 990
          }
        }
      },
      "Price": {
        "type": "object",
        "title": "Price",
        "description": "The price of a mailing, line by line. It does not depend on the destination: the price is the same for any postal code in Brazil. Amounts in the examples are illustrative; the real price depends on the account’s plan.",
        "required": [
          "currency",
          "total",
          "items"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "const": "BRL",
            "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
            "example": "BRL"
          },
          "total": {
            "type": "integer",
            "description": "Sum of all lines. This is the amount debited from the balance. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 4865
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PriceItem"
            },
            "description": "The lines of the price, always in the order base, additional_sheets, color, registered, return_receipt, restricted_delivery. Lines that would be zero are left out."
          }
        },
        "example": {
          "currency": "BRL",
          "total": 4865,
          "items": [
            {
              "type": "base",
              "quantity": 1,
              "unit_amount": 990,
              "amount": 990
            },
            {
              "type": "additional_sheets",
              "quantity": 1,
              "unit_amount": 75,
              "amount": 75
            },
            {
              "type": "color",
              "quantity": 2,
              "unit_amount": 35,
              "amount": 70
            },
            {
              "type": "registered",
              "quantity": 1,
              "unit_amount": 1175,
              "amount": 1175
            },
            {
              "type": "return_receipt",
              "quantity": 1,
              "unit_amount": 1175,
              "amount": 1175
            },
            {
              "type": "restricted_delivery",
              "quantity": 1,
              "unit_amount": 1380,
              "amount": 1380
            }
          ]
        }
      },
      "LetterDocumentInput": {
        "title": "LetterDocumentInput",
        "description": "The content to print, in JSON. Pick the way with the `type` field: `url` (up to 10 MB), `upload` (a file sent beforehand with POST /v1/uploads, up to 10 MB) or `base64` (up to 3 MB). To upload the PDF file together with the request, use multipart/form-data instead of JSON (`file` field, up to 4 MB). The PDF must be A4 portrait and fit in 6 sheets. See the Document and address area guide.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/DocumentFromUrl"
          },
          {
            "$ref": "#/components/schemas/DocumentFromUpload"
          },
          {
            "$ref": "#/components/schemas/DocumentFromBase64"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "url": "#/components/schemas/DocumentFromUrl",
            "upload": "#/components/schemas/DocumentFromUpload",
            "base64": "#/components/schemas/DocumentFromBase64"
          }
        }
      },
      "DocumentFromUrl": {
        "type": "object",
        "title": "PDF from a URL",
        "description": "CartaFlow downloads the PDF from your URL once, when the letter is created. A good fit when the PDF already lives in storage such as S3, Google Cloud Storage or Azure.",
        "required": [
          "type",
          "url"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "const": "url",
            "description": "Always `url`.",
            "example": "url"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL of a PDF file. It can be public or signed (valid for at least 10 minutes). We wait up to 10 seconds for the download.",
            "example": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
          },
          "variables": {
            "type": "object",
            "maxProperties": 100,
            "propertyNames": {
              "pattern": "^[A-Za-z0-9_]+$",
              "maxLength": 60
            },
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ],
              "maxLength": 500
            },
            "description": "Values for the markers in the PDF, such as `{{name}}` typed in a Word document and exported to PDF. Each value is written in place of its marker, at the same size and color, and the rest of the line adjusts to it, as if the value had been typed there. Values do not wrap: if a value does not fit, the rest of the line is condensed slightly, and if it still does not fit it runs past the margin; check the `preview_url`. Up to 100 variables; names use letters, digits and underscores, up to 60 characters; values are text or numbers, on one line, up to 500 characters. The PDF must have selectable text (not an image or a scan), otherwise the API answers `document_text_unreadable`. Send exactly the PDF’s markers: a missing one is `variable_missing`, an extra one is `variable_not_found`. Without this field, the PDF is printed as it is.",
            "example": {
              "nome": "Destinatário Exemplo",
              "valor": "R$ 189,90",
              "vencimento": "20/10/2026"
            }
          }
        }
      },
      "DocumentFromBase64": {
        "type": "object",
        "title": "PDF in base64",
        "description": "The PDF travels inside the JSON, encoded in base64. A good fit for small PDFs your system generates in memory, when you prefer to keep everything in JSON. Up to 3 MB of PDF; for larger files, use `url` or `upload`.",
        "required": [
          "type",
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "const": "base64",
            "description": "Always `base64`.",
            "example": "base64"
          },
          "data": {
            "type": "string",
            "contentEncoding": "base64",
            "contentMediaType": "application/pdf",
            "description": "The PDF content in standard base64, without a `data:application/pdf;base64,` prefix. Up to 3 MB once decoded (about 4 MB of base64 text), so the whole body fits in the 4.5 MB request limit. For larger PDFs, use `url` or `upload`, which take up to 10 MB.",
            "example": "JVBERi0xLjcKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFI..."
          },
          "variables": {
            "type": "object",
            "maxProperties": 100,
            "propertyNames": {
              "pattern": "^[A-Za-z0-9_]+$",
              "maxLength": 60
            },
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ],
              "maxLength": 500
            },
            "description": "Values for the markers in the PDF, such as `{{name}}` typed in a Word document and exported to PDF. Each value is written in place of its marker, at the same size and color, and the rest of the line adjusts to it, as if the value had been typed there. Values do not wrap: if a value does not fit, the rest of the line is condensed slightly, and if it still does not fit it runs past the margin; check the `preview_url`. Up to 100 variables; names use letters, digits and underscores, up to 60 characters; values are text or numbers, on one line, up to 500 characters. The PDF must have selectable text (not an image or a scan), otherwise the API answers `document_text_unreadable`. Send exactly the PDF’s markers: a missing one is `variable_missing`, an extra one is `variable_not_found`. Without this field, the PDF is printed as it is.",
            "example": {
              "nome": "Destinatário Exemplo",
              "valor": "R$ 189,90",
              "vencimento": "20/10/2026"
            }
          }
        }
      },
      "DocumentFromUpload": {
        "type": "object",
        "title": "PDF sent with POST /v1/uploads",
        "description": "A PDF you sent beforehand, in two steps: create an upload with POST /v1/uploads, send the file with a PUT to its `upload_url` and use the upload’s `id` here. A good fit for large PDFs, up to 10 MB, that do not fit in one request (the body is limited to 4.5 MB). Each upload is good for one letter only and must be used within 24 hours.",
        "required": [
          "type",
          "upload_id"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "const": "upload",
            "description": "Always `upload`.",
            "example": "upload"
          },
          "upload_id": {
            "type": "string",
            "description": "Id of the upload returned by POST /v1/uploads. Always starts with `upl_`. The file must have been sent to the `upload_url`. The upload belongs to your account, lasts 24 hours and is used up by the letter created with it. A dry run with POST /v1/letters/quote does not use it up. Possible errors: `upload_not_found`, `upload_expired`, `upload_already_used` and `upload_file_missing`.",
            "pattern": "^upl_[A-Za-z0-9]+$",
            "example": "upl_6Np3Vx8Rk2Tq"
          },
          "variables": {
            "type": "object",
            "maxProperties": 100,
            "propertyNames": {
              "pattern": "^[A-Za-z0-9_]+$",
              "maxLength": 60
            },
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ],
              "maxLength": 500
            },
            "description": "Values for the markers in the PDF, such as `{{name}}` typed in a Word document and exported to PDF. Each value is written in place of its marker, at the same size and color, and the rest of the line adjusts to it, as if the value had been typed there. Values do not wrap: if a value does not fit, the rest of the line is condensed slightly, and if it still does not fit it runs past the margin; check the `preview_url`. Up to 100 variables; names use letters, digits and underscores, up to 60 characters; values are text or numbers, on one line, up to 500 characters. The PDF must have selectable text (not an image or a scan), otherwise the API answers `document_text_unreadable`. Send exactly the PDF’s markers: a missing one is `variable_missing`, an extra one is `variable_not_found`. Without this field, the PDF is printed as it is.",
            "example": {
              "nome": "Destinatário Exemplo",
              "valor": "R$ 189,90",
              "vencimento": "20/10/2026"
            }
          }
        }
      },
      "LetterDocument": {
        "title": "LetterDocument",
        "description": "Where the letter content came from. The final PDF is at `preview_url`.",
        "oneOf": [
          {
            "type": "object",
            "title": "Uploaded PDF",
            "required": [
              "type",
              "filename",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "upload",
                "description": "The PDF was uploaded as a file: in multipart/form-data, in the `file` field, or in two steps, with POST /v1/uploads and `document.type: upload`."
              },
              "filename": {
                "type": "string",
                "description": "The name of the uploaded file: the one of the `file` part in multipart, or the upload’s `filename`.",
                "example": "fatura-outubro.pdf"
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables written into the PDF. `null` when the PDF was printed as it came.",
                "example": null
              }
            }
          },
          {
            "type": "object",
            "title": "PDF from a URL",
            "required": [
              "type",
              "url",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "url",
                "description": "The PDF came from a URL."
              },
              "url": {
                "type": "string",
                "format": "uri",
                "description": "The URL we downloaded the PDF from.",
                "example": "https://arquivos.exemplo.com.br/faturas/2026-10-0042.pdf"
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables written into the PDF. `null` when the PDF was printed as it came.",
                "example": null
              }
            }
          },
          {
            "type": "object",
            "title": "PDF in base64",
            "required": [
              "type",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "base64",
                "description": "The PDF came inside the JSON. The content is not returned; use `preview_url`."
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables written into the PDF. `null` when the PDF was printed as it came.",
                "example": null
              }
            }
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      },
      "CreateLetterRequest": {
        "type": "object",
        "title": "CreateLetterRequest",
        "required": [
          "to",
          "document"
        ],
        "additionalProperties": false,
        "properties": {
          "to": {
            "type": "object",
            "title": "AddressInput",
            "description": "Recipient. CartaFlow prints these details in the address area, which shows through the envelope window.",
            "required": [
              "name",
              "number",
              "postal_code"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-?[0-9]{3}$",
                "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
                "example": "01001-000"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": "string",
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
                "example": "Ap. 52"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Praça da Sé"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              }
            },
            "example": {
              "name": "Destinatário Exemplo",
              "postal_code": "01001-000",
              "number": "128",
              "complement": "Ap. 52"
            }
          },
          "from": {
            "type": "object",
            "title": "AddressInput",
            "description": "Sender, printed on one line above the recipient. Correios returns the letter to this address when it cannot be delivered, and sends the return receipt (`return_receipt`) here. If you leave it out, we use the account’s default sender, set in the dashboard under Configurações > Empresa (Settings > Company).",
            "required": [
              "name",
              "number",
              "postal_code"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-?[0-9]{3}$",
                "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
                "example": "01001-000"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": "string",
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
                "example": "Ap. 52"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Praça da Sé"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              }
            },
            "example": {
              "name": "Destinatário Exemplo",
              "postal_code": "01001-000",
              "number": "128",
              "complement": "Ap. 52"
            }
          },
          "document": {
            "$ref": "#/components/schemas/LetterDocumentInput"
          },
          "color": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints in color. `false` prints in black and white: a color PDF comes out in grayscale. Color printing costs extra per printed page (each printed side counts as a page).",
            "example": false
          },
          "double_sided": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints on both sides: each sheet carries two pages of the document, so the letter uses fewer sheets and costs less. `false` prints on the front of each sheet only.",
            "example": false
          },
          "address_placement": {
            "type": "string",
            "enum": [
              "first_page",
              "extra_page"
            ],
            "description": "Where CartaFlow prints the recipient’s address.\n\n**Possible values**\n\n- `first_page`: In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.\n- `extra_page`: On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged.",
            "x-enumDescriptions": {
              "first_page": "In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.",
              "extra_page": "On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged."
            },
            "default": "first_page",
            "example": "first_page"
          },
          "postal_services": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "registered",
                "return_receipt",
                "restricted_delivery"
              ],
              "x-enumDescriptions": {
                "registered": "Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.",
                "return_receipt": "Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.",
                "restricted_delivery": "Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`."
              }
            },
            "default": [],
            "description": "Optional Correios services, each with its own surcharge (a line in `price`). Without this field, or with `[]`, the letter goes as a simple letter (\"carta simples\"), with no tracking after posting. `return_receipt` and `restricted_delivery` only work together with `registered`; without it, the API answers 422 with `requires_registered`. In multipart/form-data, repeat the `postal_services[]` field once per service.\n\n**Possible values**\n\n- `registered`: Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.\n- `return_receipt`: Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.\n- `restricted_delivery`: Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`.",
            "example": [
              "registered",
              "return_receipt"
            ]
          },
          "send_date": {
            "type": "string",
            "format": "date",
            "description": "Schedules the letter for a date, formatted `YYYY-MM-DD`, from tomorrow up to 180 days ahead (Brasília time). The letter is validated now but only charged on that date, at 06:00: at that moment the balance must cover the price, otherwise the letter is canceled with `cancellation_reason: insufficient_balance`. Until then it stays `scheduled` and can be canceled at no cost. To send right away, leave this field out.",
            "example": "2026-10-20"
          },
          "reference": {
            "type": "string",
            "maxLength": 100,
            "description": "Your identifier for this letter, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters.",
            "example": "fatura-2026-10-0042"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers.",
            "example": {
              "customer_id": "1842",
              "contract": "C-2026-118"
            }
          }
        }
      },
      "Letter": {
        "type": "object",
        "title": "Letter",
        "description": "A physical letter: a document that CartaFlow prints, envelopes and posts to an address in Brazil.",
        "required": [
          "id",
          "object",
          "status",
          "to",
          "from",
          "document",
          "color",
          "double_sided",
          "address_placement",
          "postal_services",
          "pages",
          "sheets",
          "price",
          "send_date",
          "cancellation_reason",
          "failure_reason",
          "tracking_code",
          "preview_url",
          "reference",
          "metadata",
          "status_transitions",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the letter. Always starts with `ltr_`.",
            "pattern": "^ltr_[A-Za-z0-9]+$",
            "example": "ltr_8Kq2wX4mN7pR"
          },
          "object": {
            "type": "string",
            "const": "letter",
            "description": "Object type. Always `letter`.",
            "example": "letter"
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled",
              "received",
              "in_production",
              "printed",
              "posted",
              "canceled",
              "failed"
            ],
            "description": "Where the letter is. It only moves forward, never back: scheduled (only when scheduled), received, in_production, printed, posted. From scheduled or received it can move to canceled; from received, in_production or printed, to failed. A reprint in production does not change the status.\n\n**Possible values**\n\n- `scheduled`: The letter was validated and is waiting for its `send_date`. It has not been charged yet. On that date, at 06:00 Brasília time, CartaFlow debits the balance and the letter moves to `received`. If the balance does not cover the price, it moves to `canceled`. It can be canceled at no cost.\n- `received`: CartaFlow validated the document and the address, charged the letter to your balance and put it in the production queue. It can still be canceled, and the amount goes back to the balance.\n- `in_production`: The letter is part of a print batch. From this point on it can no longer be canceled.\n- `printed`: The letter was printed, folded and put in its envelope. Posting is the next step.\n- `posted`: The letter was handed to Correios, the Brazilian postal service. From here on delivery follows the postal service, and CartaFlow receives no further updates about it. A registered letter carries its Correios tracking code in `tracking_code`.\n- `canceled`: The letter was canceled before production and nothing was printed. `cancellation_reason` says why: you canceled it, or the balance did not cover a scheduled letter on its send date. If it had been charged, the amount went back to the balance.\n- `failed`: Something went wrong in production and the letter will not be posted. `failure_reason` says why. The amount went back to the balance automatically.",
            "x-enumDescriptions": {
              "scheduled": "The letter was validated and is waiting for its `send_date`. It has not been charged yet. On that date, at 06:00 Brasília time, CartaFlow debits the balance and the letter moves to `received`. If the balance does not cover the price, it moves to `canceled`. It can be canceled at no cost.",
              "received": "CartaFlow validated the document and the address, charged the letter to your balance and put it in the production queue. It can still be canceled, and the amount goes back to the balance.",
              "in_production": "The letter is part of a print batch. From this point on it can no longer be canceled.",
              "printed": "The letter was printed, folded and put in its envelope. Posting is the next step.",
              "posted": "The letter was handed to Correios, the Brazilian postal service. From here on delivery follows the postal service, and CartaFlow receives no further updates about it. A registered letter carries its Correios tracking code in `tracking_code`.",
              "canceled": "The letter was canceled before production and nothing was printed. `cancellation_reason` says why: you canceled it, or the balance did not cover a scheduled letter on its send date. If it had been charged, the amount went back to the balance.",
              "failed": "Something went wrong in production and the letter will not be posted. `failure_reason` says why. The amount went back to the balance automatically."
            },
            "example": "received"
          },
          "to": {
            "type": "object",
            "title": "Address",
            "description": "Recipient.",
            "required": [
              "name",
              "street",
              "number",
              "complement",
              "neighborhood",
              "city",
              "state",
              "postal_code"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                "example": "Praça da Sé"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                "example": "Ap. 52"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-[0-9]{3}$",
                "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                "example": "01001-000"
              }
            }
          },
          "from": {
            "type": "object",
            "title": "Address",
            "description": "Sender printed above the recipient: the one you sent or the account’s default sender.",
            "required": [
              "name",
              "street",
              "number",
              "complement",
              "neighborhood",
              "city",
              "state",
              "postal_code"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                "example": "Praça da Sé"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                "example": "Ap. 52"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-[0-9]{3}$",
                "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                "example": "01001-000"
              }
            }
          },
          "document": {
            "$ref": "#/components/schemas/LetterDocument"
          },
          "color": {
            "type": "boolean",
            "description": "`true` when printed in color.",
            "example": false
          },
          "double_sided": {
            "type": "boolean",
            "description": "`true` when printed on both sides.",
            "example": false
          },
          "address_placement": {
            "type": "string",
            "enum": [
              "first_page",
              "extra_page"
            ],
            "description": "Where the address is printed.\n\n**Possible values**\n\n- `first_page`: In the address area of the document’s first page.\n- `extra_page`: On a side of its own, the first one, at no charge.",
            "x-enumDescriptions": {
              "first_page": "In the address area of the document’s first page.",
              "extra_page": "On a side of its own, the first one, at no charge."
            },
            "example": "first_page"
          },
          "postal_services": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "registered",
                "return_receipt",
                "restricted_delivery"
              ],
              "x-enumDescriptions": {
                "registered": "Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.",
                "return_receipt": "Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.",
                "restricted_delivery": "Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`."
              }
            },
            "description": "The optional Correios services chosen at creation. Always a list: `[]` for a simple letter (\"carta simples\").\n\n**Possible values**\n\n- `registered`: Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.\n- `return_receipt`: Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.\n- `restricted_delivery`: Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`.",
            "example": []
          },
          "pages": {
            "type": "integer",
            "minimum": 1,
            "description": "Number of pages in your document, not counting the address side with `extra_page`.",
            "example": 2
          },
          "sheets": {
            "type": "integer",
            "minimum": 1,
            "maximum": 6,
            "description": "Sheets of paper in the envelope. On one side, it is `pages`. Double-sided, it is half of `pages` rounded up with `first_page`, and half of `pages` rounded down, plus 1, with `extra_page`. At most 6, counting the sheet the address adds, which is not charged.",
            "example": 2
          },
          "price": {
            "type": "object",
            "title": "Price",
            "description": "The price of the letter. It is charged to the balance at creation or, for a scheduled letter, on its send date (on the account’s plan that day). It goes back to the balance if the letter is canceled after being charged or fails in production.",
            "required": [
              "currency",
              "total",
              "items"
            ],
            "properties": {
              "currency": {
                "type": "string",
                "const": "BRL",
                "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
                "example": "BRL"
              },
              "total": {
                "type": "integer",
                "description": "Sum of all lines. This is the amount debited from the balance. In centavos (1/100 of a real): `1590` is R$ 15.90.",
                "example": 4865
              },
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PriceItem"
                },
                "description": "The lines of the price, always in the order base, additional_sheets, color, registered, return_receipt, restricted_delivery. Lines that would be zero are left out."
              }
            },
            "example": {
              "currency": "BRL",
              "total": 4865,
              "items": [
                {
                  "type": "base",
                  "quantity": 1,
                  "unit_amount": 990,
                  "amount": 990
                },
                {
                  "type": "additional_sheets",
                  "quantity": 1,
                  "unit_amount": 75,
                  "amount": 75
                },
                {
                  "type": "color",
                  "quantity": 2,
                  "unit_amount": 35,
                  "amount": 70
                },
                {
                  "type": "registered",
                  "quantity": 1,
                  "unit_amount": 1175,
                  "amount": 1175
                },
                {
                  "type": "return_receipt",
                  "quantity": 1,
                  "unit_amount": 1175,
                  "amount": 1175
                },
                {
                  "type": "restricted_delivery",
                  "quantity": 1,
                  "unit_amount": 1380,
                  "amount": 1380
                }
              ]
            }
          },
          "send_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "The scheduled send date, `YYYY-MM-DD`. `null` when the letter was sent right away.",
            "example": null
          },
          "cancellation_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "requested",
              "insufficient_balance",
              null
            ],
            "description": "Why the letter was canceled. `null` when it is not canceled.\n\n**Possible values**\n\n- `requested`: You canceled it, through the API or the dashboard.\n- `insufficient_balance`: It was a scheduled letter and, on the send date, the balance did not cover the price. Nothing was charged.",
            "example": null
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "unprintable_document",
              "damaged_in_production",
              "refused_by_carrier",
              "other",
              null
            ],
            "description": "Why the letter failed in production. `null` when it is not `failed`. When a letter fails, the amount goes back to the balance automatically.\n\n**Possible values**\n\n- `unprintable_document`: The file passed validation but could not be printed as it is.\n- `damaged_in_production`: The letter was damaged in printing, folding or enveloping and could not be produced again.\n- `refused_by_carrier`: Correios refused the letter at posting.\n- `other`: Another reason. Contact CartaFlow support from the dashboard for the details.",
            "example": null
          },
          "tracking_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Correios tracking code of a registered letter (`postal_services` with `registered`), such as `RA123456785BR`. Filled in when the letter is posted. `null` for a simple letter, which has no tracking, and before posting.",
            "example": null
          },
          "preview_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Link to the final PDF, exactly as it will be printed, address included. The link works for 60 minutes: retrieve the letter again for a fresh link. The file stays available for at least 90 days after creation (or after the send date, for a scheduled letter); `null` only after that, if the file is no longer available. For a black-and-white letter the PDF keeps the original colors: the conversion to grayscale happens at printing.",
            "example": "https://files.cartaflow.com.br/previews/ltr_8Kq2wX4mN7pR.pdf?expires=1760369400&signature=9c1f..."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100,
            "description": "Your identifier for this letter, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters. `null` when you did not send one.",
            "example": "fatura-2026-10-0042"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers. Empty object `{}` when you did not send any.",
            "example": {
              "customer_id": "1842",
              "contract": "C-2026-118"
            }
          },
          "status_transitions": {
            "type": "object",
            "title": "LetterStatusTransitions",
            "description": "When the letter reached each status. `null` for statuses it has not reached. A scheduled letter starts as scheduled, at `created_at`.",
            "required": [
              "received_at",
              "in_production_at",
              "printed_at",
              "posted_at",
              "canceled_at",
              "failed_at"
            ],
            "properties": {
              "received_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it was charged and joined the production queue: the same as `created_at`, or the send date if it was scheduled.",
                "example": "2026-10-13T14:20:00Z"
              },
              "in_production_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it went into production.",
                "example": null
              },
              "printed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it was printed and enveloped.",
                "example": null
              },
              "posted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it was handed to Correios.",
                "example": null
              },
              "canceled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it was canceled.",
                "example": null
              },
              "failed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When it failed in production.",
                "example": null
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the letter was created and received, in UTC.",
            "example": "2026-10-13T14:20:00Z"
          }
        }
      },
      "Quote": {
        "type": "object",
        "title": "Quote",
        "description": "The result of a dry run: the price of the letter on the account’s current plan, and the complete address as it would be printed. Nothing is created, charged or stored. The amount actually charged is the price at the moment of charging.",
        "required": [
          "object",
          "plan",
          "to",
          "pages",
          "sheets",
          "price"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "quote",
            "description": "Object type. Always `quote`.",
            "example": "quote"
          },
          "plan": {
            "type": "string",
            "enum": [
              "pay_as_you_go",
              "essential",
              "professional",
              "scale",
              "enterprise"
            ],
            "description": "The plan used for the calculation.\n\n**Possible values**\n\n- `pay_as_you_go`: Pay as you go. No monthly fee, higher price per mailing.\n- `essential`: Essential.\n- `professional`: Professional.\n- `scale`: Scale.\n- `enterprise`: Enterprise. 12-month contract with a committed monthly volume.",
            "x-enumDescriptions": {
              "pay_as_you_go": "Pay as you go. No monthly fee, higher price per mailing.",
              "essential": "Essential.",
              "professional": "Professional.",
              "scale": "Scale.",
              "enterprise": "Enterprise. 12-month contract with a committed monthly volume."
            },
            "example": "essential"
          },
          "to": {
            "type": "object",
            "title": "Address",
            "description": "The complete recipient, with the fields filled in from the postal code. Check it before sending.",
            "required": [
              "name",
              "street",
              "number",
              "complement",
              "neighborhood",
              "city",
              "state",
              "postal_code"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                "example": "Praça da Sé"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                "example": "Ap. 52"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-[0-9]{3}$",
                "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                "example": "01001-000"
              }
            }
          },
          "pages": {
            "type": "integer",
            "description": "Pages in the document.",
            "example": 2
          },
          "sheets": {
            "type": "integer",
            "description": "Sheets the letter would use.",
            "example": 2
          },
          "price": {
            "$ref": "#/components/schemas/Price"
          }
        }
      },
      "VerificationLetterInput": {
        "type": "object",
        "title": "VerificationLetterInput",
        "description": "Customizes the CartaFlow letter template, for this verification only. Each field you leave out comes from your company’s default letter, saved in the dashboard, and, when the company has not saved one, from the CartaFlow default. The texts sit below the envelope window. The default texts and the fixed parts, such as \"Seu código\" (\"Your code\") and the QR code instruction, are in Portuguese. Your logo, your company name, the address and the code are always printed and are not changed here. Do not use it together with `document`: the API answers 422 with `invalid_value`.",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "The letter’s title, in large type. It can use `{{empresa}}` (your company name: the trade name, or the registered name when there is none) and `{{nome}}` (the recipient’s name, from `to.name`). Any other marker in braces gives a 422 with `invalid_value`. Up to 80 characters.",
            "default": "Confirme o seu endereço",
            "example": "Confirme seu endereço, {{nome}}"
          },
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1200,
            "description": "The text right below the title, before the code. Line breaks (`\\n`) start a new paragraph. It can use `{{empresa}}` (your company name: the trade name, or the registered name when there is none) and `{{nome}}` (the recipient’s name, from `to.name`). Any other marker in braces gives a 422 with `invalid_value`. Up to 1200 characters.",
            "default": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar.",
            "example": "{{empresa}} precisa confirmar o endereço do seu cadastro. Use o código abaixo."
          },
          "footer": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "description": "The smaller text at the foot of the page. It can use `{{empresa}}` (your company name: the trade name, or the registered name when there is none) and `{{nome}}` (the recipient’s name, from `to.name`). Any other marker in braces gives a 422 with `invalid_value`. Up to 300 characters.",
            "default": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém.",
            "example": "Dúvidas? Fale com {{empresa}} pelos canais de atendimento do aplicativo."
          },
          "include_qr_code": {
            "type": "boolean",
            "default": true,
            "description": "Prints the QR code that opens the confirmation page with the code already in it: the person just taps Confirm. Only applies with `method: hosted_page`; with `method: code`, the QR code is never printed.",
            "example": true
          },
          "include_page_url": {
            "type": "boolean",
            "default": true,
            "description": "Prints the address of the confirmation page (`hosted_page_url`), for the person to open in a browser and type the code. Only applies with `method: hosted_page`; with `method: code`, the address is never printed.",
            "example": true
          }
        }
      },
      "VerificationDocumentInput": {
        "title": "VerificationDocumentInput",
        "description": "Your own PDF, instead of the CartaFlow letter template. Pick the way with the `type` field: `url` (up to 10 MB), `upload` (a file sent beforehand with POST /v1/uploads, up to 10 MB) or `base64` (up to 3 MB). This endpoint only takes JSON: to send the file itself, use the two-step upload.\n\nThe PDF follows the rules of a letter (A4 portrait, up to 6 sheets, blank address area with `address_placement: first_page`, selectable text) and has reserved markers that CartaFlow fills in:\n\n- `{{OTP_CODE}}`: required. Where the code is printed, as `123 456`, in the marker’s font, size and color. Without it, the API answers 422 with `otp_code_missing`.\n- `{{VERIFICATION_URL}}`: optional. The address of the confirmation page (`hosted_page_url`), without the code.\n- `{{QR_CODE}}`: optional. A 25 x 25 mm QR code that opens the page with the code already in it. Its top-left corner sits where the marker starts: leave that space blank, to the right of and below the marker.\n\n`{{VERIFICATION_URL}}` and `{{QR_CODE}}` only work with `method: hosted_page`; with `method: code`, the API answers 422 with `invalid_value`. Type the markers in capitals, with the braces. Other markers, such as `{{name}}`, work as in a letter: send their values in `variables`, leaving out the reserved ones (`variable_not_found`).",
        "oneOf": [
          {
            "$ref": "#/components/schemas/DocumentFromUrl"
          },
          {
            "$ref": "#/components/schemas/DocumentFromUpload"
          },
          {
            "$ref": "#/components/schemas/DocumentFromBase64"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "url": "#/components/schemas/DocumentFromUrl",
            "upload": "#/components/schemas/DocumentFromUpload",
            "base64": "#/components/schemas/DocumentFromBase64"
          }
        }
      },
      "CreateVerificationRequest": {
        "type": "object",
        "title": "CreateVerificationRequest",
        "description": "The letter comes from the CartaFlow letter template, which you can customize in `letter`, or from your own PDF, in `document`. Send one or the other, never both. A verification always goes as a simple letter (\"carta simples\"): there is no `postal_services` here.",
        "required": [
          "to",
          "method"
        ],
        "additionalProperties": false,
        "properties": {
          "to": {
            "type": "object",
            "title": "AddressInput",
            "description": "The address to verify and the name of who lives or works there.",
            "required": [
              "name",
              "number",
              "postal_code"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-?[0-9]{3}$",
                "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
                "example": "01001-000"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": "string",
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
                "example": "Ap. 52"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Praça da Sé"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              }
            },
            "example": {
              "name": "Destinatário Exemplo",
              "postal_code": "01001-000",
              "number": "128",
              "complement": "Ap. 52"
            }
          },
          "method": {
            "type": "string",
            "enum": [
              "hosted_page",
              "code"
            ],
            "description": "How the person confirms the code. It also sets what is printed on the letter.\n\n**Possible values**\n\n- `hosted_page`: The person confirms on a page with your brand, hosted by CartaFlow: through the QR code, which opens the page with the code already in it, or by typing the code at the printed address. You build no screens; the result arrives by webhook and shows in the dashboard.\n- `code`: The letter carries only the code, with no QR code and no page address. The person types it into your website or app, and your server checks it with POST /v1/verifications/{verification_id}/check.",
            "x-enumDescriptions": {
              "hosted_page": "The person confirms on a page with your brand, hosted by CartaFlow: through the QR code, which opens the page with the code already in it, or by typing the code at the printed address. You build no screens; the result arrives by webhook and shows in the dashboard.",
              "code": "The letter carries only the code, with no QR code and no page address. The person types it into your website or app, and your server checks it with POST /v1/verifications/{verification_id}/check."
            },
            "example": "hosted_page"
          },
          "letter": {
            "$ref": "#/components/schemas/VerificationLetterInput"
          },
          "document": {
            "$ref": "#/components/schemas/VerificationDocumentInput"
          },
          "color": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints in color. `false` prints in black and white: a color PDF comes out in grayscale. Color printing costs extra per printed page (each printed side counts as a page). Only applies with `document`, your own PDF. The CartaFlow letter template is always one sheet in black and white: without `document`, sending this field with a value other than the default gives a 422 with `invalid_value`.",
            "example": false
          },
          "double_sided": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints on both sides: each sheet carries two pages of the document, so the letter uses fewer sheets and costs less. `false` prints on the front of each sheet only. Only applies with `document`, your own PDF. The CartaFlow letter template is always one sheet in black and white: without `document`, sending this field with a value other than the default gives a 422 with `invalid_value`.",
            "example": false
          },
          "address_placement": {
            "type": "string",
            "enum": [
              "first_page",
              "extra_page"
            ],
            "description": "Where CartaFlow prints the recipient’s address on your PDF. Only applies with `document`, your own PDF. The CartaFlow letter template is always one sheet in black and white: without `document`, sending this field with a value other than the default gives a 422 with `invalid_value`.\n\n**Possible values**\n\n- `first_page`: In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.\n- `extra_page`: On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged.",
            "x-enumDescriptions": {
              "first_page": "In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.",
              "extra_page": "On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged."
            },
            "default": "first_page",
            "example": "first_page"
          },
          "instructions": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "description": "Text printed right below the code, on the CartaFlow letter template, telling the person where to type it. Use it with `method: code`, for example \"Open the app, go to Profile > Address and type the code\". It is also printed with `method: hosted_page` when `letter` turns off both the QR code and the page address. If you leave it out, we print \"Digite este código no site ou aplicativo de\" (\"Type this code on the website or app of\") followed by your company name. It is not printed on your own PDF: write the instruction in the document. Up to 300 characters.",
            "example": "Abra o app, vá em Perfil > Endereço e digite o código."
          },
          "return_url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Only for `method: hosted_page`. After confirming, the page shows a button that takes the person to this URL, such as the logged-in area of your site.",
            "example": "https://www.exemplo.com.br/conta"
          },
          "reference": {
            "type": "string",
            "maxLength": 100,
            "description": "Your identifier for this verification, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters.",
            "example": "cliente-1842"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers.",
            "example": {
              "customer_id": "1842",
              "contract": "C-2026-118"
            }
          }
        }
      },
      "VerificationDocument": {
        "title": "VerificationDocument",
        "description": "How the letter was made: the CartaFlow letter template or your own PDF. A copy of it, with the code hidden (`000 000`), is at `preview_url`.",
        "oneOf": [
          {
            "type": "object",
            "title": "CartaFlow letter template",
            "description": "The letter from the CartaFlow letter template, with the texts and options used: the CartaFlow default, your company’s default letter and `letter`, in that order. The texts come back with `{{empresa}}` and `{{nome}}` unfilled. With `method: code`, `include_qr_code` and `include_page_url` are always `false`.",
            "required": [
              "type",
              "title",
              "body",
              "footer",
              "include_qr_code",
              "include_page_url"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "template",
                "description": "The letter came from the CartaFlow letter template."
              },
              "title": {
                "type": "string",
                "description": "The printed title.",
                "example": "Confirme o seu endereço"
              },
              "body": {
                "type": "string",
                "description": "The text printed before the code.",
                "example": "{{empresa}} pediu a confirmação de que você recebe correspondência neste endereço. Use o código abaixo para confirmar."
              },
              "footer": {
                "type": "string",
                "description": "The text at the foot of the page.",
                "example": "O código vale por 60 dias depois da postagem e só funciona para este endereço. Não compartilhe este código com ninguém."
              },
              "include_qr_code": {
                "type": "boolean",
                "description": "`true` when the QR code was printed.",
                "example": true
              },
              "include_page_url": {
                "type": "boolean",
                "description": "`true` when the confirmation page address was printed.",
                "example": true
              }
            }
          },
          {
            "type": "object",
            "title": "Your PDF, uploaded",
            "required": [
              "type",
              "filename",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "upload",
                "description": "Your PDF was uploaded as a file: with POST /v1/uploads and `document.type: upload`, or in the dashboard."
              },
              "filename": {
                "type": "string",
                "description": "The name of the uploaded file.",
                "example": "verificacao-endereco.pdf"
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables you sent, written into the PDF. `null` when you did not send `variables`. The reserved markers, such as `{{OTP_CODE}}`, are filled in by CartaFlow and never show here.",
                "example": null
              }
            }
          },
          {
            "type": "object",
            "title": "Your PDF, from a URL",
            "required": [
              "type",
              "url",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "url",
                "description": "Your PDF came from a URL."
              },
              "url": {
                "type": "string",
                "format": "uri",
                "description": "The URL we downloaded the PDF from.",
                "example": "https://arquivos.exemplo.com.br/verificacao/modelo.pdf"
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables you sent, written into the PDF. `null` when you did not send `variables`. The reserved markers, such as `{{OTP_CODE}}`, are filled in by CartaFlow and never show here.",
                "example": null
              }
            }
          },
          {
            "type": "object",
            "title": "Your PDF, in base64",
            "required": [
              "type",
              "variables"
            ],
            "properties": {
              "type": {
                "type": "string",
                "const": "base64",
                "description": "Your PDF came inside the JSON. The content is not returned; use `preview_url`."
              },
              "variables": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true,
                "description": "The variables you sent, written into the PDF. `null` when you did not send `variables`. The reserved markers, such as `{{OTP_CODE}}`, are filled in by CartaFlow and never show here.",
                "example": null
              }
            }
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      },
      "VerificationConfirmation": {
        "type": "object",
        "title": "VerificationConfirmation",
        "description": "How and when the right code was confirmed, with everything recorded at that moment. The IP address, the location and the device data are recorded when available, with no guarantee: use them as more signals in a fraud review, never as proof of the address. The proof is the code, which only arrives in the letter. Fields that could not be recorded are `null`; confirmations recorded before 2026-10-14 have `null` in `user_agent`, `device`, `client` and `precise_location`.",
        "required": [
          "method",
          "hosted_page_entry",
          "confirmed_at",
          "ip",
          "location",
          "user_agent",
          "device",
          "client",
          "precise_location"
        ],
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "api",
              "hosted_page"
            ],
            "description": "Where the right code came in.\n\n**Possible values**\n\n- `api`: Through your server, with POST /v1/verifications/{verification_id}/check.\n- `hosted_page`: On the confirmation page hosted by CartaFlow.",
            "x-enumDescriptions": {
              "api": "Through your server, with POST /v1/verifications/{verification_id}/check.",
              "hosted_page": "On the confirmation page hosted by CartaFlow."
            },
            "example": "hosted_page"
          },
          "hosted_page_entry": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "qr_code",
              "typed",
              null
            ],
            "description": "How the person entered the code on the page. `null` when `method` is `api`.\n\n**Possible values**\n\n- `qr_code`: Scanned the QR code, which opens the page with the code already in it.\n- `typed`: Typed the code on the page.",
            "example": "qr_code"
          },
          "confirmed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the right code was confirmed. The same as `status_transitions.verified_at`.",
            "example": "2026-10-21T19:32:00Z"
          },
          "ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "The IP address, IPv4 or IPv6, the confirmation came from. With `method: hosted_page`, it is the IP of the person’s device. With `method: api`, it is the IP of your server, which called the API, not the person’s. `null` when it was not recorded.",
            "example": "198.51.100.23"
          },
          "location": {
            "type": [
              "object",
              "null"
            ],
            "title": "VerificationConfirmationLocation",
            "description": "The approximate location of the IP, estimated from the network at the time of confirmation. It is not GPS and not the verified address: a mobile network, a VPN or a proxy can point to another city or country. Only present with `method: hosted_page`. `null` with `method: api` or when it could not be estimated.",
            "required": [
              "city",
              "region",
              "country",
              "postal_code",
              "latitude",
              "longitude"
            ],
            "properties": {
              "city": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "City, such as `São Paulo`. `null` when it could not be estimated.",
                "example": "São Paulo"
              },
              "region": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Code of the region within the country (ISO 3166-2, without the country code). In Brazil, the state (UF), such as `SP`. `null` when it could not be estimated.",
                "example": "SP"
              },
              "country": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Two-letter country code (ISO 3166-1), such as `BR`. `null` when it could not be estimated.",
                "example": "BR"
              },
              "postal_code": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The postal code estimated for the IP, as the network reports it (in Brazil, often only the start of the CEP, such as `01000`). It is not the verified CEP. `null` when it could not be estimated.",
                "example": "01000"
              },
              "latitude": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": -90,
                "maximum": 90,
                "description": "Latitude estimated for the IP, in degrees. Approximate: usually the center of the city or region. `null` when it could not be estimated.",
                "example": -23.5475
              },
              "longitude": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": -180,
                "maximum": 180,
                "description": "Longitude estimated for the IP, in degrees. `null` when it could not be estimated.",
                "example": -46.6361
              }
            },
            "example": {
              "city": "São Paulo",
              "region": "SP",
              "country": "BR",
              "postal_code": "01000",
              "latitude": -23.5475,
              "longitude": -46.6361
            }
          },
          "user_agent": {
            "type": [
              "string",
              "null"
            ],
            "description": "The user agent of the browser that confirmed, as it was sent. With `method: api`, it is your server’s. `null` when none was sent.",
            "example": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1"
          },
          "device": {
            "type": [
              "object",
              "null"
            ],
            "title": "VerificationDevice",
            "description": "The device, the operating system and the browser, read from `user_agent`. A browser can report something else; treat it as a signal. `null` when `user_agent` says nothing we recognize (for example, a server’s, with `method: api`).",
            "required": [
              "type",
              "os",
              "browser"
            ],
            "properties": {
              "type": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "mobile",
                  "tablet",
                  "desktop",
                  null
                ],
                "description": "The kind of device. `null` when it could not be told.\n\n**Possible values**\n\n- `mobile`: Phone.\n- `tablet`: Tablet.\n- `desktop`: Computer.",
                "example": "mobile"
              },
              "os": {
                "type": [
                  "object",
                  "null"
                ],
                "title": "VerificationDeviceOs",
                "description": "The operating system. `null` when it was not recognized.",
                "required": [
                  "name",
                  "version"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name, such as `iOS`, `iPadOS`, `Android`, `Windows`, `macOS`, `Linux` or `ChromeOS`.",
                    "example": "iOS"
                  },
                  "version": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Version, such as `17.5`. `null` when the browser does not report it.",
                    "example": "17.5"
                  }
                }
              },
              "browser": {
                "type": [
                  "object",
                  "null"
                ],
                "title": "VerificationDeviceBrowser",
                "description": "The browser. Includes in-app browsers, such as `Instagram` and `Facebook`, and `WebView` when an iPhone app opens the page without saying which it is. `null` when it was not recognized.",
                "required": [
                  "name",
                  "version"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name, such as `Safari`, `Chrome`, `Samsung Internet`, `Firefox` or `Edge`.",
                    "example": "Safari"
                  },
                  "version": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Version, such as `17.5`. `null` when the browser does not report it.",
                    "example": "17.5"
                  }
                }
              }
            },
            "example": {
              "type": "mobile",
              "os": {
                "name": "iOS",
                "version": "17.5"
              },
              "browser": {
                "name": "Safari",
                "version": "17.5"
              }
            }
          },
          "client": {
            "type": [
              "object",
              "null"
            ],
            "title": "VerificationClient",
            "description": "What the browser told the page: language, time zone, screen and time on the page, plus the `Accept-Language` header. With `method: api`, only `accept_language`, your server’s. `null` when nothing was reported.",
            "required": [
              "language",
              "accept_language",
              "timezone",
              "screen",
              "time_on_page_ms"
            ],
            "properties": {
              "language": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The browser’s language (BCP 47), such as `pt-BR`. `null` when not reported.",
                "example": "pt-BR"
              },
              "accept_language": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The request’s `Accept-Language` header, as sent (up to 200 characters). `null` when none was sent.",
                "example": "pt-BR,pt;q=0.9"
              },
              "timezone": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The device’s time zone (IANA), such as `America/Sao_Paulo`. `null` when not reported.",
                "example": "America/Sao_Paulo"
              },
              "screen": {
                "type": [
                  "object",
                  "null"
                ],
                "title": "VerificationClientScreen",
                "description": "The device’s screen. `null` when not reported.",
                "required": [
                  "width",
                  "height",
                  "pixel_ratio"
                ],
                "properties": {
                  "width": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Width, in CSS pixels.",
                    "example": 390
                  },
                  "height": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Height, in CSS pixels.",
                    "example": 844
                  },
                  "pixel_ratio": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "description": "Physical pixels per CSS pixel, such as `3`.",
                    "example": 3
                  }
                }
              },
              "time_on_page_ms": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "description": "How long, in milliseconds, passed between opening the page and sending the code. `null` when not reported.",
                "example": 8100
              }
            },
            "example": {
              "language": "pt-BR",
              "accept_language": "pt-BR,pt;q=0.9",
              "timezone": "America/Sao_Paulo",
              "screen": {
                "width": 390,
                "height": 844,
                "pixel_ratio": 3
              },
              "time_on_page_ms": 8100
            }
          },
          "precise_location": {
            "type": [
              "object",
              "null"
            ],
            "title": "VerificationPreciseLocation",
            "description": "The device’s location, when the person chose to share it after confirming the code on the page (the browser asks for permission). It is optional, never asked for before the code and only accepted up to 30 minutes after the confirmation, once. Its accuracy depends on the device. `null` when the person did not share it, and always with `method: api`.",
            "required": [
              "latitude",
              "longitude",
              "accuracy_m",
              "distance_m",
              "shared_at",
              "ip",
              "user_agent",
              "address_coordinates"
            ],
            "properties": {
              "latitude": {
                "type": "number",
                "minimum": -90,
                "maximum": 90,
                "description": "Latitude reported by the device, in degrees.",
                "example": -23.5489
              },
              "longitude": {
                "type": "number",
                "minimum": -180,
                "maximum": 180,
                "description": "Longitude reported by the device, in degrees.",
                "example": -46.6388
              },
              "accuracy_m": {
                "type": "number",
                "minimum": 0,
                "description": "The accuracy reported by the device, in meters: the real position is likely within this radius.",
                "example": 14.5
              },
              "distance_m": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0,
                "description": "The straight-line distance, in meters, between this location and the coordinates of the verified address’s CEP (`address_coordinates`). A CEP marks a street or a stretch of it, not the number: a few hundred meters are usually normal. `null` when we do not have that CEP’s coordinates.",
                "example": 606
              },
              "shared_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the location was shared.",
                "example": "2026-10-21T19:32:40Z"
              },
              "ip": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The IP address the location was sent from. Usually the same as the confirmation’s.",
                "example": "198.51.100.23"
              },
              "user_agent": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The user agent of the browser that sent the location.",
                "example": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1"
              },
              "address_coordinates": {
                "type": [
                  "object",
                  "null"
                ],
                "title": "VerificationAddressCoordinates",
                "description": "The coordinates of the verified address’s CEP, used for `distance_m`. `null` when we do not have them.",
                "required": [
                  "latitude",
                  "longitude"
                ],
                "properties": {
                  "latitude": {
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90,
                    "description": "Latitude, in degrees.",
                    "example": -23.5503898
                  },
                  "longitude": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180,
                    "description": "Longitude, in degrees.",
                    "example": -46.633081
                  }
                }
              }
            }
          }
        }
      },
      "Verification": {
        "type": "object",
        "title": "Verification",
        "description": "A physical address verification: CartaFlow mails a letter with a code, under your brand, and the address is verified when the person confirms the code. The code never shows in this object, nor in the dashboard.",
        "required": [
          "id",
          "object",
          "status",
          "method",
          "source",
          "to",
          "document",
          "instructions",
          "return_url",
          "hosted_page_url",
          "attempts_remaining",
          "expires_at",
          "confirmation",
          "preview_url",
          "price",
          "reference",
          "metadata",
          "status_transitions",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the verification. Always starts with `ver_`.",
            "pattern": "^ver_[A-Za-z0-9]+$",
            "example": "ver_3Hd9Kp2qZ6tW"
          },
          "object": {
            "type": "string",
            "const": "verification",
            "description": "Object type. Always `verification`.",
            "example": "verification"
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "in_production",
              "awaiting_code",
              "verified",
              "failed",
              "expired",
              "canceled",
              "revoked"
            ],
            "description": "Where the verification is. It only moves forward: received, in_production, awaiting_code, verified. From received it can move to canceled; from in_production, to canceled (by CartaFlow) or revoked; from awaiting_code, to failed, expired or revoked; from verified, to revoked. Only `verified` means a confirmed address.\n\n**Possible values**\n\n- `received`: CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.\n- `in_production`: The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.\n- `awaiting_code`: The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.\n- `verified`: The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.\n- `failed`: 5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.\n- `expired`: 60 days went by after posting without the person confirming the code.\n- `canceled`: The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.\n- `revoked`: You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again.",
            "x-enumDescriptions": {
              "received": "CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.",
              "in_production": "The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.",
              "awaiting_code": "The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.",
              "verified": "The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.",
              "failed": "5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.",
              "expired": "60 days went by after posting without the person confirming the code.",
              "canceled": "The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.",
              "revoked": "You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again."
            },
            "example": "awaiting_code"
          },
          "method": {
            "type": "string",
            "enum": [
              "hosted_page",
              "code"
            ],
            "description": "How the person confirms the code.\n\n**Possible values**\n\n- `hosted_page`: On the page with your brand, through the QR code or by typing the code.\n- `code`: By typing the code into your website or app.",
            "x-enumDescriptions": {
              "hosted_page": "On the page with your brand, through the QR code or by typing the code.",
              "code": "By typing the code into your website or app."
            },
            "example": "hosted_page"
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "dashboard"
            ],
            "description": "Where the verification was created. It does not depend on how it is confirmed (see `confirmation`).\n\n**Possible values**\n\n- `api`: Through the API, with POST /v1/verifications.\n- `dashboard`: In the dashboard, by someone on your team.",
            "x-enumDescriptions": {
              "api": "Through the API, with POST /v1/verifications.",
              "dashboard": "In the dashboard, by someone on your team."
            },
            "example": "api"
          },
          "to": {
            "type": "object",
            "title": "Address",
            "description": "The address being verified.",
            "required": [
              "name",
              "street",
              "number",
              "complement",
              "neighborhood",
              "city",
              "state",
              "postal_code"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                "example": "Praça da Sé"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                "example": "Ap. 52"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-[0-9]{3}$",
                "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                "example": "01001-000"
              }
            }
          },
          "document": {
            "$ref": "#/components/schemas/VerificationDocument"
          },
          "instructions": {
            "type": [
              "string",
              "null"
            ],
            "description": "The text you sent to print below the code, on the CartaFlow letter template. `null` when you did not send one.",
            "example": null
          },
          "return_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Where the page sends the person after confirming. `null` when not set.",
            "example": "https://www.exemplo.com.br/conta"
          },
          "hosted_page_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The address of the confirmation page, with your brand (for now on the `verifica.cartaflow.com.br` domain): `https://verifica.cartaflow.com.br/{your account id}/{page token}`. It is the address printed on the letter and the one the QR code opens; the QR code carries the code with it, but this link does not, so whoever opens the link has to type the code. You can email this link or show it in your app. Treat it as an opaque address: store and use it as it came. `null` when `method` is `code`.",
            "example": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1"
          },
          "attempts_remaining": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5,
            "description": "How many more wrong codes can be entered. Starts at 5 and goes down with each wrong code, on the page or through the API. At 0 the verification moves to `failed`.",
            "example": 5
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Deadline for the person to confirm: 60 days after posting. `null` before posting.",
            "example": "2026-12-14T16:05:00Z"
          },
          "confirmation": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationConfirmation"
              },
              {
                "type": "null"
              }
            ],
            "description": "How and when the person confirmed the code: where (`method`), when, from which IP and from where, approximately. `null` until the verification is confirmed. A verification revoked after being confirmed keeps this record, but its status is `revoked`: the address no longer counts as verified.",
            "example": null
          },
          "preview_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Link to a copy of the letter as it will be printed, address included, but without the code: in its place it shows `000 000`, and in place of the QR code, a box that shows where it will be printed. The code only exists in the file CartaFlow prints: neither the API nor the dashboard can show it. The link works for 60 minutes: retrieve the verification again for a fresh link. `null` in events and webhooks, and when the file is not available.",
            "example": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3"
          },
          "price": {
            "type": "object",
            "title": "Price",
            "description": "The price charged to the balance at creation. With the CartaFlow letter template, one base mailing on your plan: a single `base` line. With your own PDF, the price of a letter with the same options: `base`, `additional_sheets` and `color`. There are never Correios services. It goes back to the balance when the verification is canceled (`canceled`); it does not when the verification is revoked (`revoked`).",
            "required": [
              "currency",
              "total",
              "items"
            ],
            "properties": {
              "currency": {
                "type": "string",
                "const": "BRL",
                "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
                "example": "BRL"
              },
              "total": {
                "type": "integer",
                "description": "Sum of all lines. This is the amount debited from the balance. In centavos (1/100 of a real): `1590` is R$ 15.90.",
                "example": 4865
              },
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PriceItem"
                },
                "description": "The lines of the price, always in the order base, additional_sheets, color, registered, return_receipt, restricted_delivery. Lines that would be zero are left out."
              }
            },
            "example": {
              "currency": "BRL",
              "total": 4865,
              "items": [
                {
                  "type": "base",
                  "quantity": 1,
                  "unit_amount": 990,
                  "amount": 990
                },
                {
                  "type": "additional_sheets",
                  "quantity": 1,
                  "unit_amount": 75,
                  "amount": 75
                },
                {
                  "type": "color",
                  "quantity": 2,
                  "unit_amount": 35,
                  "amount": 70
                },
                {
                  "type": "registered",
                  "quantity": 1,
                  "unit_amount": 1175,
                  "amount": 1175
                },
                {
                  "type": "return_receipt",
                  "quantity": 1,
                  "unit_amount": 1175,
                  "amount": 1175
                },
                {
                  "type": "restricted_delivery",
                  "quantity": 1,
                  "unit_amount": 1380,
                  "amount": 1380
                }
              ]
            }
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100,
            "description": "Your identifier for this verification, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters. `null` when you did not send one.",
            "example": "cliente-1842"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers. Empty object `{}` when you did not send any.",
            "example": {
              "customer_id": "1842",
              "contract": "C-2026-118"
            }
          },
          "status_transitions": {
            "type": "object",
            "title": "VerificationStatusTransitions",
            "description": "When the verification reached each status. `null` for statuses it has not reached. The received status happens at `created_at`. A verification revoked after being confirmed keeps `verified_at`.",
            "required": [
              "in_production_at",
              "awaiting_code_at",
              "verified_at",
              "failed_at",
              "expired_at",
              "canceled_at",
              "revoked_at"
            ],
            "properties": {
              "in_production_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the letter went into production.",
                "example": null
              },
              "awaiting_code_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the letter was posted.",
                "example": "2026-10-15T16:05:00Z"
              },
              "verified_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the person confirmed the code.",
                "example": null
              },
              "failed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the verification was locked after wrong codes.",
                "example": null
              },
              "expired_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the confirmation deadline passed.",
                "example": null
              },
              "canceled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the verification was canceled.",
                "example": null
              },
              "revoked_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the verification was revoked.",
                "example": null
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the verification was created.",
            "example": "2026-10-13T14:20:00Z"
          }
        }
      },
      "CheckVerificationRequest": {
        "type": "object",
        "title": "CheckVerificationRequest",
        "required": [
          "code"
        ],
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "pattern": "^[0-9]{6}$",
            "description": "The code the person typed: 6 digits, no spaces. Strip spaces and dashes before sending.",
            "example": "482917"
          }
        }
      },
      "VerificationCheck": {
        "type": "object",
        "title": "VerificationCheck",
        "description": "The result of a code check. A wrong code is not an API error: the response is 200, with `correct: false`.",
        "required": [
          "object",
          "correct",
          "verification"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "verification_check",
            "description": "Object type. Always `verification_check`.",
            "example": "verification_check"
          },
          "correct": {
            "type": "boolean",
            "description": "`true` when the code is right: the verification moved to `verified`, with `confirmation.method: api`. `false` when it is wrong: `attempts_remaining` went down and, if it reached 0, the verification moved to `failed`.",
            "example": true
          },
          "verification": {
            "type": "object",
            "title": "Verification",
            "description": "The verification, already updated.",
            "required": [
              "id",
              "object",
              "status",
              "method",
              "source",
              "to",
              "document",
              "instructions",
              "return_url",
              "hosted_page_url",
              "attempts_remaining",
              "expires_at",
              "confirmation",
              "preview_url",
              "price",
              "reference",
              "metadata",
              "status_transitions",
              "created_at"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique identifier of the verification. Always starts with `ver_`.",
                "pattern": "^ver_[A-Za-z0-9]+$",
                "example": "ver_3Hd9Kp2qZ6tW"
              },
              "object": {
                "type": "string",
                "const": "verification",
                "description": "Object type. Always `verification`.",
                "example": "verification"
              },
              "status": {
                "type": "string",
                "enum": [
                  "received",
                  "in_production",
                  "awaiting_code",
                  "verified",
                  "failed",
                  "expired",
                  "canceled",
                  "revoked"
                ],
                "description": "Where the verification is. It only moves forward: received, in_production, awaiting_code, verified. From received it can move to canceled; from in_production, to canceled (by CartaFlow) or revoked; from awaiting_code, to failed, expired or revoked; from verified, to revoked. Only `verified` means a confirmed address.\n\n**Possible values**\n\n- `received`: CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.\n- `in_production`: The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.\n- `awaiting_code`: The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.\n- `verified`: The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.\n- `failed`: 5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.\n- `expired`: 60 days went by after posting without the person confirming the code.\n- `canceled`: The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.\n- `revoked`: You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again.",
                "x-enumDescriptions": {
                  "received": "CartaFlow received the request, charged the price to your balance and put the letter with the code in the production queue. If you cancel now, nothing is printed and the amount goes back to the balance.",
                  "in_production": "The letter with the code is being printed and enveloped. Canceling now revokes the verification (`revoked`), with no refund.",
                  "awaiting_code": "The letter was posted. Now we wait for the person to confirm the code. They have 60 days from posting (see `expires_at`). Canceling now revokes the verification, with no refund.",
                  "verified": "The person confirmed the right code. They receive mail at the address on file. `confirmation` says how and when. You can still revoke the verification, which moves it to `revoked`.",
                  "failed": "5 wrong codes were entered. The verification was locked to stop guessing. Create a new verification to try again.",
                  "expired": "60 days went by after posting without the person confirming the code.",
                  "canceled": "The verification was canceled before posting and the amount went back to your balance. Either you canceled it while it was `received`, or CartaFlow canceled it because the letter could not be produced.",
                  "revoked": "You canceled the verification after production started: in production, awaiting the code or already verified. The amount does not go back to the balance, because production already started, and a letter that was in production is still posted. The code stops working, on the page and in the API, and the verification never shows as `verified` again."
                },
                "example": "awaiting_code"
              },
              "method": {
                "type": "string",
                "enum": [
                  "hosted_page",
                  "code"
                ],
                "description": "How the person confirms the code.\n\n**Possible values**\n\n- `hosted_page`: On the page with your brand, through the QR code or by typing the code.\n- `code`: By typing the code into your website or app.",
                "x-enumDescriptions": {
                  "hosted_page": "On the page with your brand, through the QR code or by typing the code.",
                  "code": "By typing the code into your website or app."
                },
                "example": "hosted_page"
              },
              "source": {
                "type": "string",
                "enum": [
                  "api",
                  "dashboard"
                ],
                "description": "Where the verification was created. It does not depend on how it is confirmed (see `confirmation`).\n\n**Possible values**\n\n- `api`: Through the API, with POST /v1/verifications.\n- `dashboard`: In the dashboard, by someone on your team.",
                "x-enumDescriptions": {
                  "api": "Through the API, with POST /v1/verifications.",
                  "dashboard": "In the dashboard, by someone on your team."
                },
                "example": "api"
              },
              "to": {
                "type": "object",
                "title": "Address",
                "description": "The address being verified.",
                "required": [
                  "name",
                  "street",
                  "number",
                  "complement",
                  "neighborhood",
                  "city",
                  "state",
                  "postal_code"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                    "example": "Destinatário Exemplo"
                  },
                  "street": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                    "example": "Praça da Sé"
                  },
                  "number": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10,
                    "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                    "example": "128"
                  },
                  "complement": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60,
                    "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                    "example": "Ap. 52"
                  },
                  "neighborhood": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                    "example": "Sé"
                  },
                  "city": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "City. Up to 60 characters.",
                    "example": "São Paulo"
                  },
                  "state": {
                    "type": "string",
                    "enum": [
                      "AC",
                      "AL",
                      "AP",
                      "AM",
                      "BA",
                      "CE",
                      "DF",
                      "ES",
                      "GO",
                      "MA",
                      "MT",
                      "MS",
                      "MG",
                      "PA",
                      "PB",
                      "PR",
                      "PE",
                      "PI",
                      "RJ",
                      "RN",
                      "RS",
                      "RO",
                      "RR",
                      "SC",
                      "SP",
                      "SE",
                      "TO"
                    ],
                    "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                    "x-enumDescriptions": {
                      "AC": "Acre",
                      "AL": "Alagoas",
                      "AP": "Amapá",
                      "AM": "Amazonas",
                      "BA": "Bahia",
                      "CE": "Ceará",
                      "DF": "Distrito Federal",
                      "ES": "Espírito Santo",
                      "GO": "Goiás",
                      "MA": "Maranhão",
                      "MT": "Mato Grosso",
                      "MS": "Mato Grosso do Sul",
                      "MG": "Minas Gerais",
                      "PA": "Pará",
                      "PB": "Paraíba",
                      "PR": "Paraná",
                      "PE": "Pernambuco",
                      "PI": "Piauí",
                      "RJ": "Rio de Janeiro",
                      "RN": "Rio Grande do Norte",
                      "RS": "Rio Grande do Sul",
                      "RO": "Rondônia",
                      "RR": "Roraima",
                      "SC": "Santa Catarina",
                      "SP": "São Paulo",
                      "SE": "Sergipe",
                      "TO": "Tocantins"
                    },
                    "example": "SP"
                  },
                  "postal_code": {
                    "type": "string",
                    "pattern": "^[0-9]{5}-[0-9]{3}$",
                    "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                    "example": "01001-000"
                  }
                }
              },
              "document": {
                "$ref": "#/components/schemas/VerificationDocument"
              },
              "instructions": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The text you sent to print below the code, on the CartaFlow letter template. `null` when you did not send one.",
                "example": null
              },
              "return_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Where the page sends the person after confirming. `null` when not set.",
                "example": "https://www.exemplo.com.br/conta"
              },
              "hosted_page_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "The address of the confirmation page, with your brand (for now on the `verifica.cartaflow.com.br` domain): `https://verifica.cartaflow.com.br/{your account id}/{page token}`. It is the address printed on the letter and the one the QR code opens; the QR code carries the code with it, but this link does not, so whoever opens the link has to type the code. You can email this link or show it in your app. Treat it as an opaque address: store and use it as it came. `null` when `method` is `code`.",
                "example": "https://verifica.cartaflow.com.br/acc_7Jw3Nf8Xq2Lp/9Qx2Lm7Tp4Rb8Kd3Wn6Yc1"
              },
              "attempts_remaining": {
                "type": "integer",
                "minimum": 0,
                "maximum": 5,
                "description": "How many more wrong codes can be entered. Starts at 5 and goes down with each wrong code, on the page or through the API. At 0 the verification moves to `failed`.",
                "example": 5
              },
              "expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Deadline for the person to confirm: 60 days after posting. `null` before posting.",
                "example": "2026-12-14T16:05:00Z"
              },
              "confirmation": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/VerificationConfirmation"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "How and when the person confirmed the code: where (`method`), when, from which IP and from where, approximately. `null` until the verification is confirmed. A verification revoked after being confirmed keeps this record, but its status is `revoked`: the address no longer counts as verified.",
                "example": null
              },
              "preview_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "Link to a copy of the letter as it will be printed, address included, but without the code: in its place it shows `000 000`, and in place of the QR code, a box that shows where it will be printed. The code only exists in the file CartaFlow prints: neither the API nor the dashboard can show it. The link works for 60 minutes: retrieve the verification again for a fresh link. `null` in events and webhooks, and when the file is not available.",
                "example": "https://files.cartaflow.com.br/previews/ver_3Hd9Kp2qZ6tW.pdf?expires=1760369400&signature=5d2e81b3"
              },
              "price": {
                "type": "object",
                "title": "Price",
                "description": "The price charged to the balance at creation. With the CartaFlow letter template, one base mailing on your plan: a single `base` line. With your own PDF, the price of a letter with the same options: `base`, `additional_sheets` and `color`. There are never Correios services. It goes back to the balance when the verification is canceled (`canceled`); it does not when the verification is revoked (`revoked`).",
                "required": [
                  "currency",
                  "total",
                  "items"
                ],
                "properties": {
                  "currency": {
                    "type": "string",
                    "const": "BRL",
                    "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
                    "example": "BRL"
                  },
                  "total": {
                    "type": "integer",
                    "description": "Sum of all lines. This is the amount debited from the balance. In centavos (1/100 of a real): `1590` is R$ 15.90.",
                    "example": 4865
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PriceItem"
                    },
                    "description": "The lines of the price, always in the order base, additional_sheets, color, registered, return_receipt, restricted_delivery. Lines that would be zero are left out."
                  }
                },
                "example": {
                  "currency": "BRL",
                  "total": 4865,
                  "items": [
                    {
                      "type": "base",
                      "quantity": 1,
                      "unit_amount": 990,
                      "amount": 990
                    },
                    {
                      "type": "additional_sheets",
                      "quantity": 1,
                      "unit_amount": 75,
                      "amount": 75
                    },
                    {
                      "type": "color",
                      "quantity": 2,
                      "unit_amount": 35,
                      "amount": 70
                    },
                    {
                      "type": "registered",
                      "quantity": 1,
                      "unit_amount": 1175,
                      "amount": 1175
                    },
                    {
                      "type": "return_receipt",
                      "quantity": 1,
                      "unit_amount": 1175,
                      "amount": 1175
                    },
                    {
                      "type": "restricted_delivery",
                      "quantity": 1,
                      "unit_amount": 1380,
                      "amount": 1380
                    }
                  ]
                }
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 100,
                "description": "Your identifier for this verification, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters. `null` when you did not send one.",
                "example": "cliente-1842"
              },
              "metadata": {
                "type": "object",
                "additionalProperties": {
                  "type": "string",
                  "maxLength": 500
                },
                "maxProperties": 20,
                "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers. Empty object `{}` when you did not send any.",
                "example": {
                  "customer_id": "1842",
                  "contract": "C-2026-118"
                }
              },
              "status_transitions": {
                "type": "object",
                "title": "VerificationStatusTransitions",
                "description": "When the verification reached each status. `null` for statuses it has not reached. The received status happens at `created_at`. A verification revoked after being confirmed keeps `verified_at`.",
                "required": [
                  "in_production_at",
                  "awaiting_code_at",
                  "verified_at",
                  "failed_at",
                  "expired_at",
                  "canceled_at",
                  "revoked_at"
                ],
                "properties": {
                  "in_production_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the letter went into production.",
                    "example": null
                  },
                  "awaiting_code_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the letter was posted.",
                    "example": "2026-10-15T16:05:00Z"
                  },
                  "verified_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the person confirmed the code.",
                    "example": null
                  },
                  "failed_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the verification was locked after wrong codes.",
                    "example": null
                  },
                  "expired_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the confirmation deadline passed.",
                    "example": null
                  },
                  "canceled_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the verification was canceled.",
                    "example": null
                  },
                  "revoked_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the verification was revoked.",
                    "example": null
                  }
                }
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the verification was created.",
                "example": "2026-10-13T14:20:00Z"
              }
            }
          }
        }
      },
      "PostalCode": {
        "type": "object",
        "title": "PostalCode",
        "description": "The address of a postal code (CEP), from the Correios postal code database.",
        "required": [
          "object",
          "postal_code",
          "street",
          "neighborhood",
          "city",
          "state"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "postal_code",
            "description": "Object type. Always `postal_code`.",
            "example": "postal_code"
          },
          "postal_code": {
            "type": "string",
            "pattern": "^[0-9]{5}-[0-9]{3}$",
            "description": "The postal code, formatted as `00000-000`.",
            "example": "01001-000"
          },
          "street": {
            "type": [
              "string",
              "null"
            ],
            "description": "Street of the postal code. `null` when the code covers a whole city, which is common in small towns.",
            "example": "Praça da Sé"
          },
          "neighborhood": {
            "type": [
              "string",
              "null"
            ],
            "description": "Neighborhood of the postal code. `null` when the code covers a whole city.",
            "example": "Sé"
          },
          "city": {
            "type": "string",
            "description": "City of the postal code.",
            "example": "São Paulo"
          },
          "state": {
            "type": "string",
            "enum": [
              "AC",
              "AL",
              "AP",
              "AM",
              "BA",
              "CE",
              "DF",
              "ES",
              "GO",
              "MA",
              "MT",
              "MS",
              "MG",
              "PA",
              "PB",
              "PR",
              "PE",
              "PI",
              "RJ",
              "RN",
              "RS",
              "RO",
              "RR",
              "SC",
              "SP",
              "SE",
              "TO"
            ],
            "description": "State of the postal code.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
            "x-enumDescriptions": {
              "AC": "Acre",
              "AL": "Alagoas",
              "AP": "Amapá",
              "AM": "Amazonas",
              "BA": "Bahia",
              "CE": "Ceará",
              "DF": "Distrito Federal",
              "ES": "Espírito Santo",
              "GO": "Goiás",
              "MA": "Maranhão",
              "MT": "Mato Grosso",
              "MS": "Mato Grosso do Sul",
              "MG": "Minas Gerais",
              "PA": "Pará",
              "PB": "Paraíba",
              "PR": "Paraná",
              "PE": "Pernambuco",
              "PI": "Piauí",
              "RJ": "Rio de Janeiro",
              "RN": "Rio Grande do Norte",
              "RS": "Rio Grande do Sul",
              "RO": "Rondônia",
              "RR": "Roraima",
              "SC": "Santa Catarina",
              "SP": "São Paulo",
              "SE": "Sergipe",
              "TO": "Tocantins"
            },
            "example": "SP"
          }
        }
      },
      "Account": {
        "type": "object",
        "title": "Account",
        "description": "The CartaFlow account that owns the API key used in the request.",
        "required": [
          "id",
          "object",
          "legal_name",
          "trade_name",
          "cnpj",
          "plan",
          "default_sender",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the account. Always starts with `acc_`.",
            "pattern": "^acc_[A-Za-z0-9]+$",
            "example": "acc_7Jw3Nf8Xq2Lp"
          },
          "object": {
            "type": "string",
            "const": "account",
            "description": "Object type. Always `account`.",
            "example": "account"
          },
          "legal_name": {
            "type": "string",
            "description": "Registered company name (\"razão social\").",
            "example": "Exemplo Serviços Ltda."
          },
          "trade_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Trade name (\"nome fantasia\"). It is the name shown on verification letters, next to the logo; without it, we use the registered name. Change it in the dashboard, under Configurações > Empresa (Settings > Company). `null` when not set.",
            "example": "Exemplo"
          },
          "cnpj": {
            "type": "string",
            "pattern": "^[0-9A-Z]{2}\\.[0-9A-Z]{3}\\.[0-9A-Z]{3}/[0-9A-Z]{4}-[0-9]{2}$",
            "description": "The company’s CNPJ (Brazilian company tax id), formatted. It can be alphanumeric (issued since July 2026): the first 12 characters can be capital letters or digits, and the last 2, the check digits, are always numbers. For example `12.345.678/0001-90` or `12.ABC.345/01DE-35`.",
            "example": "12.345.678/0001-90"
          },
          "plan": {
            "type": "string",
            "enum": [
              "pay_as_you_go",
              "essential",
              "professional",
              "scale",
              "enterprise"
            ],
            "description": "The current plan. It sets the price of each mailing.\n\n**Possible values**\n\n- `pay_as_you_go`: Pay as you go. No monthly fee, higher price per mailing.\n- `essential`: Essential.\n- `professional`: Professional.\n- `scale`: Scale.\n- `enterprise`: Enterprise. 12-month contract with a committed monthly volume.",
            "x-enumDescriptions": {
              "pay_as_you_go": "Pay as you go. No monthly fee, higher price per mailing.",
              "essential": "Essential.",
              "professional": "Professional.",
              "scale": "Scale.",
              "enterprise": "Enterprise. 12-month contract with a committed monthly volume."
            },
            "example": "essential"
          },
          "default_sender": {
            "type": "object",
            "title": "Address",
            "description": "Sender used when a letter has no `from`. Change it in the dashboard, under Configurações > Empresa (Settings > Company).",
            "required": [
              "name",
              "street",
              "number",
              "complement",
              "neighborhood",
              "city",
              "state",
              "postal_code"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters.",
                "example": "Praça da Sé"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. `null` when the address has none.",
                "example": "Ap. 52"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-[0-9]{3}$",
                "description": "Postal code (\"CEP\"), always formatted as `00000-000`.",
                "example": "01001-000"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the account was created.",
            "example": "2026-09-01T12:00:00Z"
          }
        }
      },
      "Balance": {
        "type": "object",
        "title": "Balance",
        "description": "The account’s prepaid balance. Each letter and each verification is debited from the balance when created. The plan’s monthly fee is billed separately and does not come out of the balance.",
        "required": [
          "object",
          "currency",
          "available",
          "pending"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "balance",
            "description": "Object type. Always `balance`.",
            "example": "balance"
          },
          "currency": {
            "type": "string",
            "const": "BRL",
            "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
            "example": "BRL"
          },
          "available": {
            "type": "integer",
            "description": "Amount available for new mailings right now. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 48865
          },
          "pending": {
            "type": "integer",
            "description": "Reserved for top-ups that depend on a payment being confirmed; they move to `available` once it is. Today balance is added at once, so it is always 0. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 0
          }
        }
      },
      "BalanceTransaction": {
        "type": "object",
        "title": "BalanceTransaction",
        "description": "One movement in or out of the balance. Use it to reconcile what each mailing cost.",
        "required": [
          "id",
          "object",
          "type",
          "amount",
          "currency",
          "balance_after",
          "source_id",
          "description",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the transaction. Always starts with `btx_`.",
            "pattern": "^btx_[A-Za-z0-9]+$",
            "example": "btx_4Lm8Qw2Zx9Kd"
          },
          "object": {
            "type": "string",
            "const": "balance_transaction",
            "description": "Object type. Always `balance_transaction`.",
            "example": "balance_transaction"
          },
          "type": {
            "type": "string",
            "enum": [
              "top_up",
              "letter",
              "verification",
              "refund",
              "credit",
              "adjustment"
            ],
            "description": "What caused the transaction.\n\n**Possible values**\n\n- `top_up`: Balance added in the dashboard or by the CartaFlow team. Positive amount.\n- `letter`: Debit for a letter. Negative amount. `source_id` is the letter id.\n- `verification`: Debit for a verification. Negative amount. `source_id` is the verification id.\n- `refund`: Refund of a letter or verification canceled after being charged, or of a letter that failed in production (`failed`). Positive amount. `source_id` is the id of the refunded object. A revoked verification (`revoked`) is not refunded.\n- `credit`: Credit granted by CartaFlow, such as the welcome credit. Positive amount.\n- `adjustment`: Adjustment made by CartaFlow support. Positive or negative. `description` explains why.",
            "x-enumDescriptions": {
              "top_up": "Balance added in the dashboard or by the CartaFlow team. Positive amount.",
              "letter": "Debit for a letter. Negative amount. `source_id` is the letter id.",
              "verification": "Debit for a verification. Negative amount. `source_id` is the verification id.",
              "refund": "Refund of a letter or verification canceled after being charged, or of a letter that failed in production (`failed`). Positive amount. `source_id` is the id of the refunded object. A revoked verification (`revoked`) is not refunded.",
              "credit": "Credit granted by CartaFlow, such as the welcome credit. Positive amount.",
              "adjustment": "Adjustment made by CartaFlow support. Positive or negative. `description` explains why."
            },
            "example": "letter"
          },
          "amount": {
            "type": "integer",
            "description": "Amount of the transaction: positive when it adds to the balance, negative when it takes from it. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": -1135
          },
          "currency": {
            "type": "string",
            "const": "BRL",
            "description": "Currency of the amounts. Always `BRL` (Brazilian real).",
            "example": "BRL"
          },
          "balance_after": {
            "type": "integer",
            "description": "Available balance right after this transaction. In centavos (1/100 of a real): `1590` is R$ 15.90.",
            "example": 48865
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id of the letter (`ltr_`) or verification (`ver_`) behind the transaction. `null` for top-ups, credits and adjustments.",
            "example": "ltr_8Kq2wX4mN7pR"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Support’s explanation for adjustments. `null` for other types.",
            "example": null
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the transaction happened.",
            "example": "2026-10-13T14:20:00Z"
          }
        }
      },
      "Event": {
        "type": "object",
        "title": "Event",
        "description": "Something that happened in your account, such as a letter being posted. CartaFlow sends each event to your webhooks and keeps it for 30 days.",
        "required": [
          "id",
          "object",
          "type",
          "data",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the event. It is the same value as the webhook-id header: use it to ignore repeated deliveries. Always starts with `evt_`.",
            "pattern": "^evt_[A-Za-z0-9]+$",
            "example": "evt_6Tq1Yz8Wm3Rb"
          },
          "object": {
            "type": "string",
            "const": "event",
            "description": "Object type. Always `event`.",
            "example": "event"
          },
          "type": {
            "type": "string",
            "enum": [
              "letter.scheduled",
              "letter.received",
              "letter.in_production",
              "letter.printed",
              "letter.posted",
              "letter.canceled",
              "letter.failed",
              "letter.updated",
              "verification.received",
              "verification.in_production",
              "verification.awaiting_code",
              "verification.verified",
              "verification.failed",
              "verification.expired",
              "verification.canceled",
              "verification.revoked"
            ],
            "description": "What happened. Every status change creates an event named `object.new_status`; a letter changed in the dashboard before production, without changing status, creates `letter.updated`.\n\n**Possible values**\n\n- `letter.scheduled`: A letter was scheduled with `send_date`. It has not been charged yet.\n- `letter.received`: A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.\n- `letter.in_production`: The letter joined a print batch and can no longer be canceled.\n- `letter.printed`: The letter was printed and enveloped.\n- `letter.posted`: The letter was handed to Correios. It is the last event of a letter that was sent.\n- `letter.canceled`: The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.\n- `letter.failed`: The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.\n- `letter.updated`: The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount.\n- `verification.received`: A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.\n- `verification.in_production`: The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.\n- `verification.awaiting_code`: The letter with the code was posted. The person can confirm once it arrives.\n- `verification.verified`: The person confirmed the right code. The address is verified.\n- `verification.failed`: 5 wrong codes were entered and the verification was locked.\n- `verification.expired`: The person did not confirm the code within 60 days of posting.\n- `verification.canceled`: The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.\n- `verification.revoked`: You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified.",
            "x-enumDescriptions": {
              "letter.scheduled": "A letter was scheduled with `send_date`. It has not been charged yet.",
              "letter.received": "A letter was charged and joined the production queue: right after creation or, if it was scheduled, on its send date. Covers letters created through the API and the dashboard.",
              "letter.in_production": "The letter joined a print batch and can no longer be canceled.",
              "letter.printed": "The letter was printed and enveloped.",
              "letter.posted": "The letter was handed to Correios. It is the last event of a letter that was sent.",
              "letter.canceled": "The letter was canceled. Check `cancellation_reason`: `requested` when you canceled it, `insufficient_balance` when a scheduled letter could not be charged on its date.",
              "letter.failed": "The letter failed in production and will not be posted. The amount went back to the balance automatically. Check `failure_reason`.",
              "letter.updated": "The letter was changed in the dashboard before production, without changing status: send date, address, file, variables, printing, Correios services or reference. `data` carries the letter as it is now. When the change altered the price of a scheduled letter, `price` has the new amount.",
              "verification.received": "A verification was created, through the API or the dashboard (see `source`), and the letter with the code is in the production queue.",
              "verification.in_production": "The letter with the code is being printed. From here on, canceling revokes the verification, with no refund.",
              "verification.awaiting_code": "The letter with the code was posted. The person can confirm once it arrives.",
              "verification.verified": "The person confirmed the right code. The address is verified.",
              "verification.failed": "5 wrong codes were entered and the verification was locked.",
              "verification.expired": "The person did not confirm the code within 60 days of posting.",
              "verification.canceled": "The verification was canceled before posting, by you or by CartaFlow, and the amount went back to the balance.",
              "verification.revoked": "You canceled the verification after production started. The code stopped working and the amount does not go back to the balance. If it was `verified`, treat the address as not verified."
            },
            "example": "letter.posted"
          },
          "data": {
            "description": "The full object as it was right after the event: a letter for `letter.*` events and a verification for `verification.*` events.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Letter"
              },
              {
                "$ref": "#/components/schemas/Verification"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the event happened.",
            "example": "2026-10-13T14:20:00Z"
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "title": "ErrorDetail",
        "required": [
          "param",
          "code",
          "message"
        ],
        "properties": {
          "param": {
            "type": "string",
            "description": "The field with the problem, in dot notation. List items use the index: `to.postal_code`, `document.variables.name`.",
            "example": "to.postal_code"
          },
          "code": {
            "type": "string",
            "enum": [
              "required",
              "unknown_parameter",
              "invalid_type",
              "invalid_value",
              "invalid_format",
              "too_short",
              "too_long",
              "out_of_range",
              "requires_registered",
              "postal_code_not_found",
              "address_incomplete",
              "document_unreachable",
              "upload_not_found",
              "upload_expired",
              "upload_already_used",
              "upload_file_missing",
              "document_invalid",
              "document_encrypted",
              "document_too_large",
              "document_page_size",
              "too_many_sheets",
              "address_area_not_blank",
              "variable_missing",
              "variable_not_found",
              "document_text_unreadable",
              "otp_code_missing"
            ],
            "description": "The problem with the field.\n\n**Possible values**\n\n- `required`: A required field is missing.\n- `unknown_parameter`: The field does not exist on this endpoint.\n- `invalid_type`: The value has the wrong type, such as text where a number is expected.\n- `invalid_value`: The value is not accepted: it is not in the list of allowed values, or it does not go with another field of the request, such as `letter` and `document` together in a verification.\n- `invalid_format`: The format is wrong: URL, date, base64, postal code or code.\n- `too_short`: The text or list is shorter than the minimum.\n- `too_long`: The text or list is longer than the maximum.\n- `out_of_range`: The number or date is outside the allowed range, such as a send_date that is not between tomorrow and 180 days ahead.\n- `requires_registered`: `return_receipt` and `restricted_delivery` only work with `registered`: the return receipt and restricted delivery are services of a registered letter.\n- `postal_code_not_found`: The postal code (CEP) does not exist in the Correios database.\n- `address_incomplete`: The address could not be completed: the field was not in the request and the postal code does not provide it. This happens with postal codes that cover a whole city and have no street or neighborhood.\n- `document_unreachable`: We could not download the PDF from the URL within 10 seconds, or the server answered with an error.\n- `upload_not_found`: There is no upload with that id in your account.\n- `upload_expired`: The upload was created more than 24 hours ago and can no longer be used.\n- `upload_already_used`: The upload was already used by another letter. Each upload is good for one letter only.\n- `upload_file_missing`: The file was never sent to the upload’s upload_url.\n- `document_invalid`: The file is not a valid PDF: it is corrupted or in another format.\n- `document_encrypted`: The PDF is password protected.\n- `document_too_large`: The PDF is larger than its way in allows: 10 MB by URL or with POST /v1/uploads, 4 MB in multipart/form-data and 3 MB in base64 (once decoded).\n- `document_page_size`: A page is not A4 portrait (210 x 297 mm).\n- `too_many_sheets`: The letter would need more than 6 sheets, the most that fits in one envelope.\n- `address_area_not_blank`: There is text or an image in the address area of the first page, where CartaFlow prints the recipient.\n- `variable_missing`: The PDF has a marker, such as {{name}}, that is missing from variables.\n- `variable_not_found`: You sent a variable the PDF does not have.\n- `document_text_unreadable`: The PDF has no selectable text: it is an image or a scan. Without text, we cannot find the markers, such as variables or the `{{OTP_CODE}}` of a verification.\n- `otp_code_missing`: The PDF of a verification has no `{{OTP_CODE}}` marker, the place where CartaFlow prints the code.",
            "x-enumDescriptions": {
              "required": "A required field is missing.",
              "unknown_parameter": "The field does not exist on this endpoint.",
              "invalid_type": "The value has the wrong type, such as text where a number is expected.",
              "invalid_value": "The value is not accepted: it is not in the list of allowed values, or it does not go with another field of the request, such as `letter` and `document` together in a verification.",
              "invalid_format": "The format is wrong: URL, date, base64, postal code or code.",
              "too_short": "The text or list is shorter than the minimum.",
              "too_long": "The text or list is longer than the maximum.",
              "out_of_range": "The number or date is outside the allowed range, such as a send_date that is not between tomorrow and 180 days ahead.",
              "requires_registered": "`return_receipt` and `restricted_delivery` only work with `registered`: the return receipt and restricted delivery are services of a registered letter.",
              "postal_code_not_found": "The postal code (CEP) does not exist in the Correios database.",
              "address_incomplete": "The address could not be completed: the field was not in the request and the postal code does not provide it. This happens with postal codes that cover a whole city and have no street or neighborhood.",
              "document_unreachable": "We could not download the PDF from the URL within 10 seconds, or the server answered with an error.",
              "upload_not_found": "There is no upload with that id in your account.",
              "upload_expired": "The upload was created more than 24 hours ago and can no longer be used.",
              "upload_already_used": "The upload was already used by another letter. Each upload is good for one letter only.",
              "upload_file_missing": "The file was never sent to the upload’s upload_url.",
              "document_invalid": "The file is not a valid PDF: it is corrupted or in another format.",
              "document_encrypted": "The PDF is password protected.",
              "document_too_large": "The PDF is larger than its way in allows: 10 MB by URL or with POST /v1/uploads, 4 MB in multipart/form-data and 3 MB in base64 (once decoded).",
              "document_page_size": "A page is not A4 portrait (210 x 297 mm).",
              "too_many_sheets": "The letter would need more than 6 sheets, the most that fits in one envelope.",
              "address_area_not_blank": "There is text or an image in the address area of the first page, where CartaFlow prints the recipient.",
              "variable_missing": "The PDF has a marker, such as {{name}}, that is missing from variables.",
              "variable_not_found": "You sent a variable the PDF does not have.",
              "document_text_unreadable": "The PDF has no selectable text: it is an image or a scan. Without text, we cannot find the markers, such as variables or the `{{OTP_CODE}}` of a verification.",
              "otp_code_missing": "The PDF of a verification has no `{{OTP_CODE}}` marker, the place where CartaFlow prints the code."
            },
            "example": "postal_code_not_found"
          },
          "message": {
            "type": "string",
            "description": "Explanation for people, in the Accept-Language language.",
            "example": "Não encontramos este CEP. Confira os 8 dígitos."
          }
        }
      },
      "Error": {
        "type": "object",
        "title": "Error",
        "description": "Every error response has this shape, on every endpoint.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message",
              "request_id",
              "doc_url",
              "details"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "billing_error",
                  "permission_error",
                  "not_found_error",
                  "conflict_error",
                  "validation_error",
                  "rate_limit_error",
                  "api_error"
                ],
                "description": "The error category. Each type maps to an HTTP status.\n\n**Possible values**\n\n- `invalid_request_error`: HTTP 400 or 413. We could not read the request: the JSON is malformed, a header is wrong or the body is too large.\n- `authentication_error`: HTTP 401. The API key is missing, invalid or revoked.\n- `billing_error`: HTTP 402. The account balance does not cover the operation.\n- `permission_error`: HTTP 403. The account cannot perform this operation right now.\n- `not_found_error`: HTTP 404. The object or the endpoint does not exist.\n- `conflict_error`: HTTP 409. The request is valid, but the current state of the object does not allow the operation.\n- `validation_error`: HTTP 422. We read the request, but one or more fields have invalid values. The `details` list says which ones and why.\n- `rate_limit_error`: HTTP 429. The account went over its requests-per-second limit.\n- `api_error`: HTTP 500 or 503. Something failed on CartaFlow’s side. It is not a problem with your request.",
                "x-enumDescriptions": {
                  "invalid_request_error": "HTTP 400 or 413. We could not read the request: the JSON is malformed, a header is wrong or the body is too large.",
                  "authentication_error": "HTTP 401. The API key is missing, invalid or revoked.",
                  "billing_error": "HTTP 402. The account balance does not cover the operation.",
                  "permission_error": "HTTP 403. The account cannot perform this operation right now.",
                  "not_found_error": "HTTP 404. The object or the endpoint does not exist.",
                  "conflict_error": "HTTP 409. The request is valid, but the current state of the object does not allow the operation.",
                  "validation_error": "HTTP 422. We read the request, but one or more fields have invalid values. The `details` list says which ones and why.",
                  "rate_limit_error": "HTTP 429. The account went over its requests-per-second limit.",
                  "api_error": "HTTP 500 or 503. Something failed on CartaFlow’s side. It is not a problem with your request."
                },
                "example": "validation_error"
              },
              "code": {
                "type": "string",
                "enum": [
                  "invalid_json",
                  "unsupported_content_type",
                  "invalid_idempotency_key",
                  "request_too_large",
                  "api_key_missing",
                  "api_key_invalid",
                  "api_key_revoked",
                  "insufficient_balance",
                  "account_suspended",
                  "resource_not_found",
                  "endpoint_not_found",
                  "postal_code_not_found",
                  "letter_not_cancelable",
                  "verification_not_cancelable",
                  "verification_not_awaiting_code",
                  "idempotency_key_reused",
                  "idempotency_key_in_use",
                  "invalid_parameters",
                  "rate_limit_exceeded",
                  "internal_error",
                  "service_unavailable"
                ],
                "description": "The exact error. Use this field in your code: it never changes meaning. New codes may be added, so handle an unknown code by its `type`.\n\n**Possible values**\n\n- `invalid_json`: The request body is not valid JSON.\n- `unsupported_content_type`: The Content-Type header is not accepted on this endpoint.\n- `invalid_idempotency_key`: The Idempotency-Key header is empty or longer than 255 characters.\n- `request_too_large`: The request body is larger than 4.5 MB, the most the API accepts in one request.\n- `api_key_missing`: The request has no Authorization header.\n- `api_key_invalid`: The key does not exist or is mistyped.\n- `api_key_revoked`: The key was revoked in the dashboard.\n- `insufficient_balance`: The available balance is lower than the price of the mailing.\n- `account_suspended`: The account is suspended and cannot create mailings.\n- `resource_not_found`: There is no object with that id in your account.\n- `endpoint_not_found`: The path or the HTTP method does not exist in the API.\n- `postal_code_not_found`: The postal code (CEP) you looked up does not exist in the Correios database.\n- `letter_not_cancelable`: The letter’s status is no longer scheduled or received: it is already in production, posted or failed.\n- `verification_not_cancelable`: The verification ended without a confirmation (`failed` or `expired`) and cannot be canceled or revoked.\n- `verification_not_awaiting_code`: The verification is not waiting for a code: the letter was not posted yet, or the verification is already finished, canceled or revoked.\n- `idempotency_key_reused`: This Idempotency-Key was already used with a different body or on another endpoint in the last 24 hours.\n- `idempotency_key_in_use`: A request with the same Idempotency-Key is still being processed.\n- `invalid_parameters`: One or more fields have invalid values.\n- `rate_limit_exceeded`: The account made more requests per second than its limit.\n- `internal_error`: Unexpected error at CartaFlow.\n- `service_unavailable`: The API is temporarily unavailable, for maintenance or overload.",
                "x-enumDescriptions": {
                  "invalid_json": "The request body is not valid JSON.",
                  "unsupported_content_type": "The Content-Type header is not accepted on this endpoint.",
                  "invalid_idempotency_key": "The Idempotency-Key header is empty or longer than 255 characters.",
                  "request_too_large": "The request body is larger than 4.5 MB, the most the API accepts in one request.",
                  "api_key_missing": "The request has no Authorization header.",
                  "api_key_invalid": "The key does not exist or is mistyped.",
                  "api_key_revoked": "The key was revoked in the dashboard.",
                  "insufficient_balance": "The available balance is lower than the price of the mailing.",
                  "account_suspended": "The account is suspended and cannot create mailings.",
                  "resource_not_found": "There is no object with that id in your account.",
                  "endpoint_not_found": "The path or the HTTP method does not exist in the API.",
                  "postal_code_not_found": "The postal code (CEP) you looked up does not exist in the Correios database.",
                  "letter_not_cancelable": "The letter’s status is no longer scheduled or received: it is already in production, posted or failed.",
                  "verification_not_cancelable": "The verification ended without a confirmation (`failed` or `expired`) and cannot be canceled or revoked.",
                  "verification_not_awaiting_code": "The verification is not waiting for a code: the letter was not posted yet, or the verification is already finished, canceled or revoked.",
                  "idempotency_key_reused": "This Idempotency-Key was already used with a different body or on another endpoint in the last 24 hours.",
                  "idempotency_key_in_use": "A request with the same Idempotency-Key is still being processed.",
                  "invalid_parameters": "One or more fields have invalid values.",
                  "rate_limit_exceeded": "The account made more requests per second than its limit.",
                  "internal_error": "Unexpected error at CartaFlow.",
                  "service_unavailable": "The API is temporarily unavailable, for maintenance or overload."
                },
                "example": "invalid_parameters"
              },
              "message": {
                "type": "string",
                "description": "Explanation for people, in Portuguese or English according to the Accept-Language header. The wording may change; do not match on it in code.",
                "example": "Um campo tem problema. Veja details."
              },
              "request_id": {
                "type": "string",
                "description": "Id of this request. Send it to support when you need help. Same as the Request-Id header.",
                "example": "req_9Vb4Xk2Lq8Mz"
              },
              "doc_url": {
                "type": "string",
                "format": "uri",
                "description": "Link to this code in the documentation.",
                "example": "https://docs.cartaflow.com.br/errors#invalid_parameters"
              },
              "details": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "$ref": "#/components/schemas/ErrorDetail"
                },
                "description": "Every field with a problem, all at once. Only present for `validation_error`; `null` for other types."
              }
            }
          }
        }
      },
      "LetterList": {
        "type": "object",
        "title": "LetterList",
        "description": "A page of letters, newest first.",
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Object type. Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Letter"
            },
            "description": "The items on this page."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true` when there are more items after this page.",
            "example": false
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Send this value as `cursor` to fetch the next page. `null` when this is the last page.",
            "example": null
          }
        }
      },
      "VerificationList": {
        "type": "object",
        "title": "VerificationList",
        "description": "A page of verifications, newest first.",
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Object type. Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Verification"
            },
            "description": "The items on this page."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true` when there are more items after this page.",
            "example": false
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Send this value as `cursor` to fetch the next page. `null` when this is the last page.",
            "example": null
          }
        }
      },
      "BalanceTransactionList": {
        "type": "object",
        "title": "BalanceTransactionList",
        "description": "A page of balance transactions, newest first.",
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Object type. Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BalanceTransaction"
            },
            "description": "The items on this page."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true` when there are more items after this page.",
            "example": false
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Send this value as `cursor` to fetch the next page. `null` when this is the last page.",
            "example": null
          }
        }
      },
      "EventList": {
        "type": "object",
        "title": "EventList",
        "description": "A page of events, newest first.",
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Object type. Always `list`.",
            "example": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            },
            "description": "The items on this page."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true` when there are more items after this page.",
            "example": false
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Send this value as `cursor` to fetch the next page. `null` when this is the last page.",
            "example": null
          }
        }
      },
      "CreateLetterUpload": {
        "type": "object",
        "title": "CreateLetterUpload",
        "description": "The same body as the JSON version, in multipart/form-data, with the PDF file in the `file` field instead of `document`. Use it when you have the file and want to send it with the data, in a single request.\n\nIn multipart/form-data, nested fields use brackets: `to[name]`, `to[postal_code]`, `variables[name]`, `metadata[customer_id]`. Lists repeat the field with `[]`: `postal_services[]=registered`. Booleans are sent as `true` or `false`.",
        "required": [
          "file",
          "to"
        ],
        "additionalProperties": false,
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "contentMediaType": "application/pdf",
            "description": "The document to print. A PDF file, A4 portrait, up to 4 MB: the whole request body is limited to 4.5 MB. For larger PDFs, up to 10 MB, use JSON with `document.type: url`, or send the file beforehand with POST /v1/uploads and use `document.type: upload`."
          },
          "to": {
            "type": "object",
            "title": "AddressInput",
            "description": "Recipient. CartaFlow prints these details in the address area, which shows through the envelope window.",
            "required": [
              "name",
              "number",
              "postal_code"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-?[0-9]{3}$",
                "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
                "example": "01001-000"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": "string",
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
                "example": "Ap. 52"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Praça da Sé"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              }
            },
            "example": {
              "name": "Destinatário Exemplo",
              "postal_code": "01001-000",
              "number": "128",
              "complement": "Ap. 52"
            }
          },
          "from": {
            "type": "object",
            "title": "AddressInput",
            "description": "Sender, printed on one line above the recipient. Correios returns the letter to this address when it cannot be delivered, and sends the return receipt (`return_receipt`) here. If you leave it out, we use the account’s default sender, set in the dashboard under Configurações > Empresa (Settings > Company).",
            "required": [
              "name",
              "number",
              "postal_code"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Name of the person or company, as it should appear on the envelope. Up to 60 characters.",
                "example": "Destinatário Exemplo"
              },
              "postal_code": {
                "type": "string",
                "pattern": "^[0-9]{5}-?[0-9]{3}$",
                "description": "Postal code (\"CEP\"), 8 digits, with or without the hyphen: `01001-000` or `01001000`. It must exist in the postal code database; the fields you leave out come from it. Responses always return it with the hyphen.",
                "example": "01001-000"
              },
              "number": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10,
                "description": "Building number. It is a string because some numbers include letters, such as `128A`. Use `S/N` (\"sem número\") when the address has no number. Up to 10 characters.",
                "example": "128"
              },
              "complement": {
                "type": "string",
                "maxLength": 60,
                "description": "Address complement: apartment, block, suite, floor. Up to 60 characters.",
                "example": "Ap. 52"
              },
              "street": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "description": "Street type and name, as written in Brazil: \"Rua\", \"Avenida\", \"Travessa\", \"Praça\" followed by the name. Without the number. Up to 100 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Praça da Sé"
              },
              "neighborhood": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Neighborhood (\"bairro\"), part of every Brazilian address. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "Sé"
              },
              "city": {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "City. Up to 60 characters. Optional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.",
                "example": "São Paulo"
              },
              "state": {
                "type": "string",
                "enum": [
                  "AC",
                  "AL",
                  "AP",
                  "AM",
                  "BA",
                  "CE",
                  "DF",
                  "ES",
                  "GO",
                  "MA",
                  "MT",
                  "MS",
                  "MG",
                  "PA",
                  "PB",
                  "PR",
                  "PE",
                  "PI",
                  "RJ",
                  "RN",
                  "RS",
                  "RO",
                  "RR",
                  "SC",
                  "SP",
                  "SE",
                  "TO"
                ],
                "description": "State: the two-letter code of the Brazilian state (\"UF\"), in capitals.\n\nOptional: when you leave it out, we fill it in from the postal code. When you send it, we use your value.\n\n**Possible values**\n\n- `AC`: Acre\n- `AL`: Alagoas\n- `AP`: Amapá\n- `AM`: Amazonas\n- `BA`: Bahia\n- `CE`: Ceará\n- `DF`: Distrito Federal\n- `ES`: Espírito Santo\n- `GO`: Goiás\n- `MA`: Maranhão\n- `MT`: Mato Grosso\n- `MS`: Mato Grosso do Sul\n- `MG`: Minas Gerais\n- `PA`: Pará\n- `PB`: Paraíba\n- `PR`: Paraná\n- `PE`: Pernambuco\n- `PI`: Piauí\n- `RJ`: Rio de Janeiro\n- `RN`: Rio Grande do Norte\n- `RS`: Rio Grande do Sul\n- `RO`: Rondônia\n- `RR`: Roraima\n- `SC`: Santa Catarina\n- `SP`: São Paulo\n- `SE`: Sergipe\n- `TO`: Tocantins",
                "x-enumDescriptions": {
                  "AC": "Acre",
                  "AL": "Alagoas",
                  "AP": "Amapá",
                  "AM": "Amazonas",
                  "BA": "Bahia",
                  "CE": "Ceará",
                  "DF": "Distrito Federal",
                  "ES": "Espírito Santo",
                  "GO": "Goiás",
                  "MA": "Maranhão",
                  "MT": "Mato Grosso",
                  "MS": "Mato Grosso do Sul",
                  "MG": "Minas Gerais",
                  "PA": "Pará",
                  "PB": "Paraíba",
                  "PR": "Paraná",
                  "PE": "Pernambuco",
                  "PI": "Piauí",
                  "RJ": "Rio de Janeiro",
                  "RN": "Rio Grande do Norte",
                  "RS": "Rio Grande do Sul",
                  "RO": "Rondônia",
                  "RR": "Roraima",
                  "SC": "Santa Catarina",
                  "SP": "São Paulo",
                  "SE": "Sergipe",
                  "TO": "Tocantins"
                },
                "example": "SP"
              }
            },
            "example": {
              "name": "Destinatário Exemplo",
              "postal_code": "01001-000",
              "number": "128",
              "complement": "Ap. 52"
            }
          },
          "variables": {
            "type": "object",
            "maxProperties": 100,
            "propertyNames": {
              "pattern": "^[A-Za-z0-9_]+$",
              "maxLength": 60
            },
            "additionalProperties": {
              "type": [
                "string",
                "number"
              ],
              "maxLength": 500
            },
            "description": "Values for the markers in the PDF, such as `{{name}}` typed in a Word document and exported to PDF. Each value is written in place of its marker, at the same size and color, and the rest of the line adjusts to it, as if the value had been typed there. Values do not wrap: if a value does not fit, the rest of the line is condensed slightly, and if it still does not fit it runs past the margin; check the `preview_url`. Up to 100 variables; names use letters, digits and underscores, up to 60 characters; values are text or numbers, on one line, up to 500 characters. The PDF must have selectable text (not an image or a scan), otherwise the API answers `document_text_unreadable`. Send exactly the PDF’s markers: a missing one is `variable_missing`, an extra one is `variable_not_found`. Without this field, the PDF is printed as it is.",
            "example": {
              "nome": "Destinatário Exemplo",
              "valor": "R$ 189,90",
              "vencimento": "20/10/2026"
            }
          },
          "color": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints in color. `false` prints in black and white: a color PDF comes out in grayscale. Color printing costs extra per printed page (each printed side counts as a page).",
            "example": false
          },
          "double_sided": {
            "type": "boolean",
            "default": false,
            "description": "`true` prints on both sides: each sheet carries two pages of the document, so the letter uses fewer sheets and costs less. `false` prints on the front of each sheet only.",
            "example": false
          },
          "address_placement": {
            "type": "string",
            "enum": [
              "first_page",
              "extra_page"
            ],
            "description": "Where CartaFlow prints the recipient’s address.\n\n**Possible values**\n\n- `first_page`: In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.\n- `extra_page`: On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged.",
            "x-enumDescriptions": {
              "first_page": "In the address area of your document’s first page (90 x 45 mm, 20 mm from the left and 45 mm from the top). That area must be blank in your PDF. Default.",
              "extra_page": "On a side of its own, the first one, which shows through the envelope window. Use it when your layout fills the address area. It takes a side that would otherwise be blank, when there is one: the back of the first page when printing on one side, or the spare side of a double-sided document with an odd number of pages. A double-sided document with an even number of pages gets one more sheet at the front. The address is never charged."
            },
            "default": "first_page",
            "example": "first_page"
          },
          "postal_services": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "registered",
                "return_receipt",
                "restricted_delivery"
              ],
              "x-enumDescriptions": {
                "registered": "Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.",
                "return_receipt": "Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.",
                "restricted_delivery": "Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`."
              }
            },
            "default": [],
            "description": "Optional Correios services, each with its own surcharge (a line in `price`). Without this field, or with `[]`, the letter goes as a simple letter (\"carta simples\"), with no tracking after posting. `return_receipt` and `restricted_delivery` only work together with `registered`; without it, the API answers 422 with `requires_registered`. In multipart/form-data, repeat the `postal_services[]` field once per service.\n\n**Possible values**\n\n- `registered`: Registered letter (\"carta registrada\"): the letter is posted with registration at Correios and gets a Correios tracking code, shown in `tracking_code` once it is posted.\n- `return_receipt`: Return receipt (\"aviso de recebimento\", AR): Correios returns a card signed by whoever received the letter to the sender printed on the envelope. Requires `registered`.\n- `restricted_delivery`: Restricted delivery (\"mão própria\", MP): Correios delivers only to the person named on the envelope. Requires `registered`.",
            "example": [
              "registered",
              "return_receipt"
            ]
          },
          "send_date": {
            "type": "string",
            "format": "date",
            "description": "Schedules the letter for a date, formatted `YYYY-MM-DD`, from tomorrow up to 180 days ahead (Brasília time). The letter is validated now but only charged on that date, at 06:00: at that moment the balance must cover the price, otherwise the letter is canceled with `cancellation_reason: insufficient_balance`. Until then it stays `scheduled` and can be canceled at no cost. To send right away, leave this field out.",
            "example": "2026-10-20"
          },
          "reference": {
            "type": "string",
            "maxLength": 100,
            "description": "Your identifier for this letter, such as the invoice number or the customer id in your system. Shown in the dashboard and usable as a filter when listing. It does not have to be unique. Up to 100 characters.",
            "example": "fatura-2026-10-0042"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Key-value pairs to store your own data with the object, such as your customer or contract id. Returned in every response and webhook and never printed. Up to 20 keys; keys up to 40 characters and string values up to 500 characters. Do not store sensitive data such as passwords or card numbers.",
            "example": {
              "customer_id": "1842",
              "contract": "C-2026-118"
            }
          }
        }
      },
      "CreateUploadRequest": {
        "type": "object",
        "title": "CreateUploadRequest",
        "description": "Details of the PDF you are about to send. The response carries an `upload_url` you send the file to with a PUT; then use the upload’s `id` in a letter with `document.type: upload`.",
        "required": [
          "filename",
          "size"
        ],
        "additionalProperties": false,
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The PDF’s file name, such as `fatura-outubro.pdf`. It shows in the letter’s `document.filename` and in the dashboard. From 1 to 255 characters.",
            "example": "fatura-outubro.pdf"
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760,
            "description": "The file size in bytes, from 1 to 10485760 (10 MB). Above that, the API answers 422 with `out_of_range`.",
            "example": 7340032
          }
        }
      },
      "Upload": {
        "type": "object",
        "title": "Upload",
        "description": "A place to send a large PDF before creating the letter. Send the file with a PUT to `upload_url` within 2 hours and use the `id` in a letter within 24 hours. Each upload belongs to your account and is good for one letter only.",
        "required": [
          "id",
          "object",
          "filename",
          "size",
          "upload_url",
          "upload_url_expires_at",
          "expires_at",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the upload. Use it as `document.upload_id` when creating the letter. Always starts with `upl_`.",
            "pattern": "^upl_[A-Za-z0-9]+$",
            "example": "upl_6Np3Vx8Rk2Tq"
          },
          "object": {
            "type": "string",
            "const": "upload",
            "description": "Object type. Always `upload`.",
            "example": "upload"
          },
          "filename": {
            "type": "string",
            "description": "The file name, as you sent it.",
            "example": "fatura-outubro.pdf"
          },
          "size": {
            "type": "integer",
            "description": "The file size in bytes, as you declared it.",
            "example": 7340032
          },
          "upload_url": {
            "type": "string",
            "format": "uri",
            "description": "Signed HTTPS URL to send the file to. Send the PDF bytes in the body of a PUT, with the `Content-Type: application/pdf` header and no `Authorization` header: the signature is already in the URL. A 2xx response confirms the file arrived. It works for 2 hours (until `upload_url_expires_at`). Treat the URL as a secret and do not store it: it is not shown anywhere else.",
            "example": "https://files.cartaflow.com.br/uploads/upl_6Np3Vx8Rk2Tq?token=4f8a2c91d7"
          },
          "upload_url_expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Until when `upload_url` accepts the file: 2 hours after creation. If the time runs out before you send it, create another upload.",
            "example": "2026-10-13T14:35:00Z"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Until when the upload can be used in a letter: 24 hours after creation. After that, `document.upload_id` gets a 422 with `upload_expired`.",
            "example": "2026-10-14T14:20:00Z"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the upload was created.",
            "example": "2026-10-13T14:20:00Z"
          }
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 255,
          "example": "fatura-2026-10-0042"
        },
        "description": "A unique value per operation, such as the invoice id in your system or a UUID. If you repeat the request with the same key within 24 hours, the API returns the first response instead of creating another object. Recommended on every POST. Up to 255 characters."
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20,
          "example": 20
        },
        "description": "How many items to return per page, from 1 to 100. Default: 20."
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "example": "eyJpZCI6Imx0cl84S3Eyd1g0bU43cFIifQ"
        },
        "description": "The `next_cursor` of the previous page. Leave it out to fetch the first page."
      },
      "CreatedAfter": {
        "name": "created_after",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2026-10-01T00:00:00Z"
        },
        "description": "Only items created at or after this moment. ISO 8601 date and time."
      },
      "CreatedBefore": {
        "name": "created_before",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2026-11-01T00:00:00Z"
        },
        "description": "Only items created before this moment. ISO 8601 date and time."
      },
      "Reference": {
        "name": "reference",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "example": "fatura-2026-10-0042"
        },
        "description": "Only items with exactly this `reference`."
      },
      "LetterId": {
        "name": "letter_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "example": "ltr_8Kq2wX4mN7pR"
        },
        "description": "The letter id, starting with `ltr_`."
      },
      "VerificationId": {
        "name": "verification_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "example": "ver_3Hd9Kp2qZ6tW"
        },
        "description": "The verification id, starting with `ver_`."
      },
      "EventId": {
        "name": "event_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "example": "evt_6Tq1Yz8Wm3Rb"
        },
        "description": "The event id, starting with `evt_`."
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "The request could not be read: malformed JSON, wrong Content-Type or invalid Idempotency-Key.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "invalid_json",
                "message": "The request body is not valid JSON.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#invalid_json",
                "details": null
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The API key is missing, invalid or revoked.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "api_key_invalid",
                "message": "This API key does not exist. Copy the key again from the dashboard.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#api_key_invalid",
                "details": null
              }
            }
          }
        }
      },
      "InsufficientBalance": {
        "description": "The balance does not cover the price. Nothing was created or charged.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "billing_error",
                "code": "insufficient_balance",
                "message": "The available balance (R$ 4.10) does not cover this mailing (R$ 9.90). Top up your balance in the dashboard.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#insufficient_balance",
                "details": null
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The account is suspended.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "permission_error",
                "code": "account_suspended",
                "message": "This account is suspended. Contact support from the dashboard.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#account_suspended",
                "details": null
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "There is no object with that id in your account.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "not_found_error",
                "code": "resource_not_found",
                "message": "There is no letter with id ltr_8Kq2wX4mN7pR in this account.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#resource_not_found",
                "details": null
              }
            }
          }
        }
      },
      "RequestTooLarge": {
        "description": "The request body is larger than 4.5 MB. Nothing was created. Send the PDF by URL or with POST /v1/uploads.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "request_too_large",
                "message": "The request body is larger than 4.5 MB. Send the PDF by URL or with POST /v1/uploads, which take up to 10 MB.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#request_too_large",
                "details": null
              }
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "The Idempotency-Key was already used with a different body, or the first request with it is still running.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "conflict_error",
                "code": "idempotency_key_reused",
                "message": "This Idempotency-Key was already used with different parameters. Use a new key for a different operation.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#idempotency_key_reused",
                "details": null
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded (50 per second per account). Wait for Retry-After.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
                "message": "Too many requests. Try again in 1 second.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#rate_limit_exceeded",
                "details": null
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "Error on CartaFlow’s side. Retry with the same Idempotency-Key.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "api_error",
                "code": "internal_error",
                "message": "Unexpected error. Try again; if it persists, send the request_id to support.",
                "request_id": "req_9Vb4Xk2Lq8Mz",
                "doc_url": "https://docs.cartaflow.com.br/en/errors#internal_error",
                "details": null
              }
            }
          }
        }
      }
    },
    "headers": {
      "RequestId": {
        "description": "Id of this request, such as `req_9Vb4Xk2Lq8Mz`. Send it to support when you need help.",
        "schema": {
          "type": "string",
          "example": "req_9Vb4Xk2Lq8Mz"
        }
      },
      "RateLimitLimit": {
        "description": "How many requests per second the account can make, across all of its keys.",
        "schema": {
          "type": "integer",
          "example": 50
        }
      },
      "RateLimitRemaining": {
        "description": "How many requests are left in the current window.",
        "schema": {
          "type": "integer",
          "example": 49
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the current window resets.",
        "schema": {
          "type": "integer",
          "example": 1
        }
      },
      "IdempotentReplayed": {
        "description": "`true` when this response replays an earlier request with the same Idempotency-Key.",
        "schema": {
          "type": "boolean",
          "example": true
        }
      }
    }
  }
}
