{"openapi":"3.1.0","info":{"title":"Courio API","version":"1.0.0","description":"Courio sends physical letters on behalf of AI agents. No account is needed: an agent quotes, creates, pays and follows a letter with plain HTTPS calls.\n\n## Agent flow\n\n1. **Quote** - `POST /v1/letters/quote` with sender, recipient, a service level and the document (`pdf_base64`, `pdf_url` or `text`). You get a frozen price (EUR, VAT included, plus the USD amount for x402) valid 24 h, and a `quote_id`. Check `GET /v1/coverage` first if unsure a country/service exists.\n2. **Create** - `POST /v1/letters` with the `quote_id` and a `payment_method`.\n   - `stripe`: answers **201** with `payment.checkout_url` (card-only Stripe Checkout). A human opens it and pays.\n   - `x402` (may be disabled on a deployment: you then get **422** `payment_method_unavailable`, use `stripe`): the first call without payment answers **402** with the requirements in the `PAYMENT-REQUIRED` header (and the body). Sign a USDC payment and resend the *same* request with the `PAYMENT-SIGNATURE` header; the answer is **201** with `PAYMENT-RESPONSE`. Official x402 clients cap a single payment at $1 by default: raise the spend limit to at least the quote's `usd_amount`, or the client will refuse to pay.\n3. **Pay** - the letter is created in `awaiting_payment` (Stripe) or directly `paid` (x402).\n4. **Poll or listen** - `GET /v1/letters/{id}` or receive webhooks (below). Statuses: `awaiting_payment`, `paid`, `submitted`, `in_transit`, `delivered`, `returned`, `failed`, `manual_pending`, `manual_done`, `expired`.\n\n**Payment is irreversible once made**: after payment the letter is printed and mailed; it cannot be cancelled or edited. If Courio cannot fulfil it, the payment is refunded automatically (Stripe) or by hand (x402). Check the document and the addresses before paying.\n\nEvery `POST /v1/*` requires an `Idempotency-Key` header. Errors are `application/problem+json` with `type`, `title`, `status`, `code` and a one-sentence `hint` meant for an agent.\n\n## Authentication\n\nOptional. Without a key you can quote, create and read a letter you know the id of (redacted view). A `ck_` API key (`Authorization: Bearer ck_...`) attaches letters to your key, gives the full view of your letters, enables `GET /v1/letters` and has its own daily limit.\n\n## Webhooks\n\nPass `webhook_url` (public https) when creating a letter. The creation response returns a `webhook_secret` (only there). Each status change is POSTed as JSON `{event_id, letter_id, status, occurred_at, data}` with the header `Courio-Signature: t=<unix seconds>,v1=<hex>` where `v1 = HMAC-SHA256(webhook_secret, \"<t>.<raw body>\")`. Verify the signature on the raw body and reject old timestamps. Any non-2xx answer is retried with backoff for 24 h; deduplicate on `event_id`.\n\n## MCP\n\nThe same capabilities are exposed as MCP tools at `/mcp` (streamable HTTP, stateless, POST only)."},"servers":[{"url":"https://api.courio.si"}],"tags":[{"name":"Letters"},{"name":"Coverage"}],"paths":{"/v1/letters/quote":{"post":{"tags":["Letters"],"operationId":"quoteLetter","summary":"Get a frozen price for a letter","description":"Validates addresses and the document, runs content moderation and routes to a provider. Creates no letter and charges nothing. The quote is valid 24 h.","security":[{},{"apiKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Unique key (max 255 chars) per logical request. Repeating a request with the same key and body replays the stored response; same key with another body is `idempotency_key_reused`.","schema":{"type":"string","maxLength":255},"example":"b1c6a1e2-7f3d-4a52-9c10-3f1b7c2d9e11"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"},"example":{"service":"registered_ar","sender":{"name":"Acme SAS","address_lines":["12 rue de la Paix"],"postal_code":"75002","city":"Paris","country":"FR","email":"ops@acme.example"},"recipient":{"name":"Erika Mustermann","address_lines":["Unter den Linden 1"],"postal_code":"10117","city":"Berlin","country":"DE"},"document":{"text":"Madame, Monsieur,\n\nPar la présente, nous vous notifions la résiliation du contrat n° 4711.\n\nCordialement"},"options":{"color":false,"duplex":true},"currency":"EUR"}}}},"responses":{"200":{"description":"Quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"},"example":{"quote_id":"qt_7Hn2KdQ4VxLm9RwYb3TcZs5P","expires_at":"2026-11-02T10:00:00.000Z","price":{"amount":1290,"currency":"EUR","tax_included":true,"usd_amount":1405},"legal_product":{"code":"DE_REGISTERED_AR","local_name":"Einschreiben Rückschein","english_name":"Registered mail with return receipt","proof":"delivery"},"estimated_delivery_days":{"min":2,"max":4},"fulfillment":"automated","pages":1,"warnings":[]}}}},"400":{"description":"- `validation_failed`: The body, query or path did not validate; `errors` lists the fields.\n- `idempotency_key_required`: Idempotency-Key header missing.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["validation_failed","idempotency_key_required"]}}}]},"example":{"type":"urn:courio:error:validation_failed","title":"Validation failed","status":400,"code":"validation_failed","hint":"The body, query or path did not validate; `errors` lists the fields."}}}},"401":{"description":"- `unauthorized`: Authorization header present but not a valid ck_ API key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["unauthorized"]}}}]},"example":{"type":"urn:courio:error:unauthorized","title":"Unauthorized","status":401,"code":"unauthorized","hint":"Authorization header present but not a valid ck_ API key."}}}},"422":{"description":"- `idempotency_key_reused`: Idempotency-Key already used with a different body.\n- `invalid_address`: An address cannot be used (`field` says which).\n- `product_unavailable`: No provider delivers this service to this country.\n- `document_invalid`: The PDF/text is unusable (`reason`).\n- `content_rejected`: Moderation refused the content.\n- `amount_limit_exceeded`: The price exceeds the per-letter cap.\n- `not_routable`: No provider could be routed for this letter.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["idempotency_key_reused","invalid_address","product_unavailable","document_invalid","content_rejected","amount_limit_exceeded","not_routable"]}}}]},"example":{"type":"urn:courio:error:idempotency_key_reused","title":"Idempotency key reused","status":422,"code":"idempotency_key_reused","hint":"Idempotency-Key already used with a different body."}}}},"429":{"description":"- `limit_exceeded`: Daily limit reached: letters (IP, sender email, wallet or API key) or quotes (IP or API key); retry after `retry_after` seconds with the same request and key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["limit_exceeded"]}}}]},"example":{"type":"urn:courio:error:limit_exceeded","title":"Limit exceeded","status":429,"code":"limit_exceeded","hint":"Daily limit reached: letters (IP, sender email, wallet or API key) or quotes (IP or API key); retry after `retry_after` seconds with the same request and key."}}}},"500":{"description":"- `internal_error`: Unexpected server error.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["internal_error"]}}}]},"example":{"type":"urn:courio:error:internal_error","title":"Internal error","status":500,"code":"internal_error","hint":"Unexpected server error."}}}},"503":{"description":"- `moderation_unavailable`: Moderation could not run; nothing was accepted, retry.\n- `pricing_unavailable`: No EUR/USD rate available; retry shortly.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["moderation_unavailable","pricing_unavailable"]}}}]},"example":{"type":"urn:courio:error:moderation_unavailable","title":"Moderation unavailable","status":503,"code":"moderation_unavailable","hint":"Moderation could not run; nothing was accepted, retry."}}}}}}},"/v1/letters":{"post":{"tags":["Letters"],"operationId":"createLetter","summary":"Create a letter from a quote and pay for it","description":"With `payment_method: \"stripe\"` answers 201 with a Checkout URL. With `\"x402\"`, call once without `PAYMENT-SIGNATURE` to get the 402 and its `PAYMENT-REQUIRED` header, then resend the same request with the signed payment. The 402 (and a 429 `limit_exceeded`) is never stored by the idempotency layer: retry the same request with the same key. Payment is irreversible once made.","security":[{},{"apiKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Unique key (max 255 chars) per logical request. Repeating a request with the same key and body replays the stored response; same key with another body is `idempotency_key_reused`.","schema":{"type":"string","maxLength":255},"example":"b1c6a1e2-7f3d-4a52-9c10-3f1b7c2d9e11"},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"description":"x402 only: base64 JSON of the signed x402 v2 PaymentPayload for `accepts[0]` of the 402 response.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLetterRequest"},"example":{"quote_id":"qt_7Hn2KdQ4VxLm9RwYb3TcZs5P","payment_method":"stripe","webhook_url":"https://agent.example/hooks/courio"}}}},"responses":{"201":{"description":"Letter created. Stripe: `awaiting_payment` with a Checkout URL. x402: payment settled, letter `paid`/`submitted`.","headers":{"PAYMENT-RESPONSE":{"description":"x402 only: base64 JSON settlement response.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedLetter"},"examples":{"stripe":{"summary":"Stripe","value":{"letter_id":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs","status":"awaiting_payment","payment":{"checkout_url":"https://checkout.stripe.com/c/pay/cs_live_a1b2c3","expires_at":"2026-11-01T10:30:00.000Z"},"webhook_secret":"whsec_3f1d9c0e7a4b"}},"x402":{"summary":"x402","value":{"letter_id":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs","status":"submitted","payment":{"method":"x402","payer":"0x2222222222222222222222222222222222222222","transaction":"0xabc123","network":"eip155:8453"},"webhook_secret":"whsec_3f1d9c0e7a4b"}}}}}},"400":{"description":"- `validation_failed`: The body, query or path did not validate; `errors` lists the fields.\n- `idempotency_key_required`: Idempotency-Key header missing.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["validation_failed","idempotency_key_required"]}}}]},"example":{"type":"urn:courio:error:validation_failed","title":"Validation failed","status":400,"code":"validation_failed","hint":"The body, query or path did not validate; `errors` lists the fields."}}}},"401":{"description":"- `unauthorized`: Authorization header present but not a valid ck_ API key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["unauthorized"]}}}]},"example":{"type":"urn:courio:error:unauthorized","title":"Unauthorized","status":401,"code":"unauthorized","hint":"Authorization header present but not a valid ck_ API key."}}}},"402":{"description":"x402 only: payment required or rejected. Body is a problem+json extended with the x402 requirements (`x402Version`, `accepts`, ...) and the `quote_id` and `price` (USD). The same requirements are base64-encoded in `PAYMENT-REQUIRED`. Codes: `payment_required`, `payment_invalid`.","headers":{"PAYMENT-REQUIRED":{"description":"Base64 JSON PaymentRequired (x402 v2).","schema":{"type":"string"}}},"content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"type":"object","properties":{"code":{"enum":["payment_required","payment_invalid"]},"reason":{"type":"string"},"accepts":{"type":"array","items":{"type":"object"}},"quote_id":{"type":"string"},"price":{"type":"object"}}}]},"example":{"type":"urn:courio:error:payment_required","title":"Payment required","status":402,"code":"payment_required","hint":"Pay with x402: sign a payment for accepts[0] and resend this same request with the PAYMENT-SIGNATURE header. Official x402 clients cap a payment at $1 by default: allow this price.","x402Version":2,"error":"payment_required","resource":{"url":"https://api.courio.example/v1/letters","description":"Registered letter with return receipt, FR to DE","mimeType":"application/json"},"accepts":[{"scheme":"exact","network":"eip155:8453","amount":"1405000","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","payTo":"0x1111111111111111111111111111111111111111","maxTimeoutSeconds":120}],"quote_id":"qt_7Hn2KdQ4VxLm9RwYb3TcZs5P","price":{"amount":1405,"currency":"USD"}}}}},"404":{"description":"- `quote_not_found`: No quote with this id.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["quote_not_found"]}}}]},"example":{"type":"urn:courio:error:quote_not_found","title":"Quote not found","status":404,"code":"quote_not_found","hint":"No quote with this id."}}}},"409":{"description":"- `quote_already_used`: The quote already created a letter; `letter_id` points to it.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["quote_already_used"]}}}]},"example":{"type":"urn:courio:error:quote_already_used","title":"Quote already used","status":409,"code":"quote_already_used","hint":"The quote already created a letter; `letter_id` points to it.","letter_id":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs"}}}},"410":{"description":"- `quote_expired`: The 24 h quote validity elapsed; request a new quote.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["quote_expired"]}}}]},"example":{"type":"urn:courio:error:quote_expired","title":"Quote expired","status":410,"code":"quote_expired","hint":"The 24 h quote validity elapsed; request a new quote."}}}},"422":{"description":"- `idempotency_key_reused`: Idempotency-Key already used with a different body.\n- `payment_method_unavailable`: The payment method is disabled on this deployment (x402 may be off); use `stripe`.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["idempotency_key_reused","payment_method_unavailable"]}}}]},"example":{"type":"urn:courio:error:idempotency_key_reused","title":"Idempotency key reused","status":422,"code":"idempotency_key_reused","hint":"Idempotency-Key already used with a different body."}}}},"429":{"description":"- `limit_exceeded`: Daily limit reached: letters (IP, sender email, wallet or API key) or quotes (IP or API key); retry after `retry_after` seconds with the same request and key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["limit_exceeded"]}}}]},"example":{"type":"urn:courio:error:limit_exceeded","title":"Limit exceeded","status":429,"code":"limit_exceeded","hint":"Daily limit reached: letters (IP, sender email, wallet or API key) or quotes (IP or API key); retry after `retry_after` seconds with the same request and key."}}}},"500":{"description":"- `internal_error`: Unexpected server error.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["internal_error"]}}}]},"example":{"type":"urn:courio:error:internal_error","title":"Internal error","status":500,"code":"internal_error","hint":"Unexpected server error."}}}},"503":{"description":"- `payment_unavailable`: Stripe or the x402 facilitator is unavailable; retry the same request.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["payment_unavailable"]}}}]},"example":{"type":"urn:courio:error:payment_unavailable","title":"Payment unavailable","status":503,"code":"payment_unavailable","hint":"Stripe or the x402 facilitator is unavailable; retry the same request."}}}}}},"get":{"tags":["Letters"],"operationId":"listLetters","summary":"List the letters created with your API key","security":[{"apiKey":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["awaiting_payment","paid","submitted","in_transit","delivered","returned","failed","manual_pending","manual_done","expired"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"description":"`next_cursor` of the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Page of letters, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LetterList"},"example":{"data":[{"letter_id":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs","status":"in_transit","service":"registered_ar","legal_product":{"code":"DE_REGISTERED_AR","local_name":"Einschreiben Rückschein","english_name":"Registered mail with return receipt","proof":"delivery"},"price":{"amount":1290,"currency":"EUR","tax_included":true,"usd_amount":1405},"recipient":{"name":"Erika Mustermann","address_lines":["Unter den Linden 1"],"postal_code":"10117","city":"Berlin","country":"DE"},"tracking_number":"RR123456789DE","proofs":[],"timeline":[{"status":"paid","at":"2026-11-01T10:01:00.000Z"},{"status":"submitted","at":"2026-11-01T10:01:08.000Z"},{"status":"in_transit","at":"2026-11-02T08:30:00.000Z"}]}],"next_cursor":null}}}},"400":{"description":"- `validation_failed`: The body, query or path did not validate; `errors` lists the fields.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["validation_failed"]}}}]},"example":{"type":"urn:courio:error:validation_failed","title":"Validation failed","status":400,"code":"validation_failed","hint":"The body, query or path did not validate; `errors` lists the fields."}}}},"401":{"description":"- `unauthorized`: Authorization header present but not a valid ck_ API key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["unauthorized"]}}}]},"example":{"type":"urn:courio:error:unauthorized","title":"Unauthorized","status":401,"code":"unauthorized","hint":"Authorization header present but not a valid ck_ API key."}}}},"500":{"description":"- `internal_error`: Unexpected server error.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["internal_error"]}}}]},"example":{"type":"urn:courio:error:internal_error","title":"Internal error","status":500,"code":"internal_error","hint":"Unexpected server error."}}}}}}},"/v1/letters/{id}":{"get":{"tags":["Letters"],"operationId":"getLetter","summary":"Read a letter and its timeline","description":"Public with the letter id (recipient redacted to city and country, no tracking details beyond status); full view when called with the API key that created it. Proof URLs are signed and short-lived.","security":[{},{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^ltr_[0-9A-Za-z]{24}$"},"example":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs"}],"responses":{"200":{"description":"Letter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Letter"},"example":{"letter_id":"ltr_Xk3mPq9RtWb2LvZc8YdNf4Hs","status":"in_transit","service":"registered_ar","legal_product":{"code":"DE_REGISTERED_AR","local_name":"Einschreiben Rückschein","english_name":"Registered mail with return receipt","proof":"delivery"},"price":{"amount":1290,"currency":"EUR","tax_included":true,"usd_amount":1405},"recipient":{"name":"Erika Mustermann","address_lines":["Unter den Linden 1"],"postal_code":"10117","city":"Berlin","country":"DE"},"tracking_number":"RR123456789DE","proofs":[],"timeline":[{"status":"paid","at":"2026-11-01T10:01:00.000Z"},{"status":"submitted","at":"2026-11-01T10:01:08.000Z"},{"status":"in_transit","at":"2026-11-02T08:30:00.000Z"}]}}}},"401":{"description":"- `unauthorized`: Authorization header present but not a valid ck_ API key.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["unauthorized"]}}}]},"example":{"type":"urn:courio:error:unauthorized","title":"Unauthorized","status":401,"code":"unauthorized","hint":"Authorization header present but not a valid ck_ API key."}}}},"404":{"description":"- `letter_not_found`: No letter with this id.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["letter_not_found"]}}}]},"example":{"type":"urn:courio:error:letter_not_found","title":"Letter not found","status":404,"code":"letter_not_found","hint":"No letter with this id."}}}},"500":{"description":"- `internal_error`: Unexpected server error.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["internal_error"]}}}]},"example":{"type":"urn:courio:error:internal_error","title":"Internal error","status":500,"code":"internal_error","hint":"Unexpected server error."}}}}}}},"/v1/coverage":{"get":{"tags":["Coverage"],"operationId":"getCoverage","summary":"Countries and services Courio delivers, with starting prices","parameters":[{"name":"country","in":"query","required":false,"description":"Uppercase ISO 3166-1 alpha-2 code.","schema":{"type":"string","pattern":"^[A-Z]{2}$"},"example":"DE"}],"responses":{"200":{"description":"Coverage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageResponse"},"example":{"countries":[{"country":"DE","services":[{"service":"registered_ar","available":true,"fulfillment":"automated","from_price":{"amount":1290,"currency":"EUR"},"delivery_days":{"min":2,"max":4},"legal_product":{"code":"DE_REGISTERED_AR","local_name":"Einschreiben Rückschein","english_name":"Registered mail with return receipt","proof":"delivery"}},{"service":"standard","available":false}]}]}}}},"400":{"description":"- `validation_failed`: The body, query or path did not validate; `errors` lists the fields.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["validation_failed"]}}}]},"example":{"type":"urn:courio:error:validation_failed","title":"Validation failed","status":400,"code":"validation_failed","hint":"The body, query or path did not validate; `errors` lists the fields."}}}},"500":{"description":"- `internal_error`: Unexpected server error.","content":{"application/problem+json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"code":{"enum":["internal_error"]}}}]},"example":{"type":"urn:courio:error:internal_error","title":"Internal error","status":500,"code":"internal_error","hint":"Unexpected server error."}}}}}}}},"components":{"schemas":{"QuoteRequest":{"type":"object","properties":{"service":{"type":"string","enum":["standard","tracked","registered","registered_ar"]},"sender":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"company":{"type":"string","maxLength":80},"address_lines":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","maxLength":80}},"postal_code":{"type":"string","maxLength":16},"city":{"type":"string","minLength":1,"maxLength":60},"country":{"type":"string"},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["name","address_lines","postal_code","city","country"]},"recipient":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"company":{"type":"string","maxLength":80},"address_lines":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","maxLength":80}},"postal_code":{"type":"string","maxLength":16},"city":{"type":"string","minLength":1,"maxLength":60},"country":{"type":"string"},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["name","address_lines","postal_code","city","country"]},"document":{"anyOf":[{"type":"object","properties":{"pdf_base64":{"type":"string","minLength":1}},"required":["pdf_base64"],"additionalProperties":false},{"type":"object","properties":{"pdf_url":{"type":"string","format":"uri"}},"required":["pdf_url"],"additionalProperties":false},{"type":"object","properties":{"text":{"type":"string","minLength":1},"format":{"default":"plain","type":"string","enum":["plain","markdown"]}},"required":["text"],"additionalProperties":false}]},"options":{"default":{"color":false,"duplex":true},"type":"object","properties":{"color":{"default":false,"type":"boolean"},"duplex":{"default":true,"type":"boolean"}}},"currency":{"default":"EUR","type":"string","enum":["EUR","USD"]}},"required":["service","sender","recipient","document"]},"QuoteResponse":{"type":"object","properties":{"quote_id":{"type":"string"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"price":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"maximum":9007199254740991},"currency":{"type":"string","enum":["EUR","USD"]},"tax_included":{"type":"boolean"},"usd_amount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","currency","tax_included","usd_amount"],"additionalProperties":false},"legal_product":{"type":"object","properties":{"code":{"type":"string"},"local_name":{"type":"string"},"english_name":{"type":"string"},"proof":{"type":"string","enum":["none","deposit","delivery"]}},"required":["code","local_name","english_name","proof"],"additionalProperties":false},"estimated_delivery_days":{"type":"object","properties":{"min":{"type":"integer","minimum":0,"maximum":9007199254740991},"max":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["min","max"],"additionalProperties":false},"fulfillment":{"type":"string","enum":["automated","manual"]},"pages":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"warnings":{"type":"array","items":{"type":"string"}}},"required":["quote_id","expires_at","price","legal_product","estimated_delivery_days","fulfillment","pages","warnings"],"additionalProperties":false},"CreateLetterRequest":{"type":"object","properties":{"quote_id":{"type":"string","minLength":1},"payment_method":{"type":"string","enum":["stripe","x402"]},"webhook_url":{"type":"string","format":"uri"}},"required":["quote_id","payment_method"]},"Letter":{"type":"object","properties":{"letter_id":{"type":"string"},"status":{"type":"string"},"service":{"type":"string","enum":["standard","tracked","registered","registered_ar"]},"legal_product":{"type":"object","properties":{"code":{"type":"string"},"local_name":{"type":"string"},"english_name":{"type":"string"},"proof":{"type":"string","enum":["none","deposit","delivery"]}},"required":["code","local_name","english_name","proof"],"additionalProperties":false},"price":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"maximum":9007199254740991},"currency":{"type":"string","enum":["EUR","USD"]},"tax_included":{"type":"boolean"},"usd_amount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","currency","tax_included","usd_amount"],"additionalProperties":false},"recipient":{"anyOf":[{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"company":{"type":"string","maxLength":80},"address_lines":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","maxLength":80}},"postal_code":{"type":"string","maxLength":16},"city":{"type":"string","minLength":1,"maxLength":60},"country":{},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["name","address_lines","postal_code","city","country"],"additionalProperties":false},{"type":"object","properties":{"city":{"type":"string"},"country":{"type":"string"}},"required":["city","country"],"additionalProperties":false}]},"tracking_number":{"type":"string"},"proofs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["kind","url","expires_at"],"additionalProperties":false}},"timeline":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["status","at"],"additionalProperties":false}},"payment":{"type":"object","properties":{"checkout_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["checkout_url","expires_at"],"additionalProperties":false},"webhook_secret":{"type":"string"}},"required":["letter_id","status","service","legal_product","price","recipient","proofs","timeline"],"additionalProperties":false},"LetterList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"letter_id":{"type":"string"},"status":{"type":"string"},"service":{"type":"string","enum":["standard","tracked","registered","registered_ar"]},"legal_product":{"type":"object","properties":{"code":{"type":"string"},"local_name":{"type":"string"},"english_name":{"type":"string"},"proof":{"type":"string","enum":["none","deposit","delivery"]}},"required":["code","local_name","english_name","proof"],"additionalProperties":false},"price":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"maximum":9007199254740991},"currency":{"type":"string","enum":["EUR","USD"]},"tax_included":{"type":"boolean"},"usd_amount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["amount","currency","tax_included","usd_amount"],"additionalProperties":false},"recipient":{"anyOf":[{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"company":{"type":"string","maxLength":80},"address_lines":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","maxLength":80}},"postal_code":{"type":"string","maxLength":16},"city":{"type":"string","minLength":1,"maxLength":60},"country":{},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["name","address_lines","postal_code","city","country"],"additionalProperties":false},{"type":"object","properties":{"city":{"type":"string"},"country":{"type":"string"}},"required":["city","country"],"additionalProperties":false}]},"tracking_number":{"type":"string"},"proofs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["kind","url","expires_at"],"additionalProperties":false}},"timeline":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["status","at"],"additionalProperties":false}},"payment":{"type":"object","properties":{"checkout_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["checkout_url","expires_at"],"additionalProperties":false},"webhook_secret":{"type":"string"}},"required":["letter_id","status","service","legal_product","price","recipient","proofs","timeline"],"additionalProperties":false}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"],"additionalProperties":false},"CoverageResponse":{"type":"object","properties":{"countries":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"services":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"service":{"type":"string","enum":["standard","tracked","registered","registered_ar"]},"available":{"type":"boolean","const":true},"fulfillment":{"type":"string","enum":["automated","manual"]},"from_price":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"maximum":9007199254740991},"currency":{"type":"string","enum":["EUR","USD"]}},"required":["amount","currency"],"additionalProperties":false},"delivery_days":{"type":"object","properties":{"min":{"type":"integer","minimum":0,"maximum":9007199254740991},"max":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["min","max"],"additionalProperties":false},"legal_product":{"type":"object","properties":{"code":{"type":"string"},"local_name":{"type":"string"},"english_name":{"type":"string"},"proof":{"type":"string","enum":["none","deposit","delivery"]}},"required":["code","local_name","english_name","proof"],"additionalProperties":false}},"required":["service","available","fulfillment","from_price","delivery_days","legal_product"],"additionalProperties":false},{"type":"object","properties":{"service":{"type":"string","enum":["standard","tracked","registered","registered_ar"]},"available":{"type":"boolean","const":false}},"required":["service","available"],"additionalProperties":false}]}}},"required":["country","services"],"additionalProperties":false}}},"required":["countries"],"additionalProperties":false},"CreatedLetter":{"type":"object","required":["letter_id","status","payment","webhook_secret"],"properties":{"letter_id":{"type":"string"},"status":{"type":"string","description":"`awaiting_payment` for Stripe; for x402 the status after the inline submission (`submitted`, or `paid` while the worker continues)."},"payment":{"oneOf":[{"type":"object","required":["checkout_url","expires_at"],"properties":{"checkout_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time"}}},{"type":"object","required":["method","payer","transaction","network"],"properties":{"method":{"const":"x402"},"payer":{"type":"string"},"transaction":{"type":"string"},"network":{"type":"string"}}}]},"webhook_secret":{"type":"string","description":"Signing secret of outgoing webhooks. Shown only here."}}},"Problem":{"type":"object","required":["type","title","status","code","hint"],"additionalProperties":true,"properties":{"type":{"type":"string","pattern":"^urn:courio:error:","example":"urn:courio:error:quote_expired"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","enum":["validation_failed","idempotency_key_required","idempotency_key_reused","unauthorized","payment_required","payment_invalid","letter_not_found","quote_not_found","quote_already_used","quote_expired","invalid_address","product_unavailable","document_invalid","content_rejected","amount_limit_exceeded","limit_exceeded","internal_error","moderation_unavailable","pricing_unavailable","payment_unavailable","payment_method_unavailable","not_routable"]},"hint":{"type":"string","description":"One sentence telling an agent how to proceed."}}}},"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"ck_...","description":"Optional courio API key."}}}}