{"openapi":"3.1.0","info":{"title":"PaperAgent REST API","version":"1.0.0","description":"Physical letters through USPS. Preview and approve the exact total before creating an order. No printing or mailing until payment settles. Cancellation is handled by support."},"servers":[{"url":"https://paperagent.dev"}],"paths":{"/v1/account/session":{"get":{"operationId":"customer_session","summary":"Read the Google browser session and CSRF token.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"email":{"type":"string"},"sender_name":{"type":"string"},"sender_confirmed":{"type":"boolean"},"kyc_status":{"type":"string"},"csrf_token":{"type":"string"},"return_addresses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"verificationMethod":{"type":"string"},"verifiedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"accountId":{"type":"string"}},"required":["id","address","verificationMethod","verifiedAt","createdAt","accountId"],"additionalProperties":false}}},"required":["account_id","email","sender_name","sender_confirmed","kyc_status","csrf_token","return_addresses"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/logout":{"post":{"operationId":"customer_logout","summary":"Sign out of this browser session.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/sender/validate":{"post":{"operationId":"validate_sender","summary":"Validate a customer return address and show postal corrections.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sender_name":{"type":"string","minLength":1,"maxLength":120},"address":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["line1","city","state","zip5"]}},"required":["sender_name","address"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"validation_id":{"type":"string"},"sender_name":{"type":"string"},"address":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["line1","city","state","zip5"],"additionalProperties":{}},"corrections":{"type":"array","items":{"type":"string"}},"expires_in":{"type":"number"}},"required":["validation_id","sender_name","address","corrections","expires_in"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/sender":{"post":{"operationId":"confirm_sender","summary":"Confirm the validated address receives the customer’s mail.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"validation_id":{"type":"string","minLength":1,"maxLength":100},"receives_mail_here":{"type":"boolean","const":true}},"required":["validation_id","receives_mail_here"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"return_address_id":{"type":"string"},"verification_method":{"type":"string","const":"customer_confirmed"},"description":{"type":"string"}},"required":["return_address_id","verification_method","description"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/connections":{"get":{"operationId":"list_agent_connections","summary":"List connected agents and their unverified labels.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"connections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"client_name":{"type":"string"},"scope":{"type":"string"},"created_at":{"type":"string"},"revoked_at":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","client_name","scope","created_at","revoked_at"],"additionalProperties":false}}},"required":["connections"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/connections/{id}":{"delete":{"operationId":"disconnect_agent","summary":"Revoke an agent’s entire access and refresh token family.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/api-keys":{"get":{"operationId":"list_customer_keys","summary":"List API key metadata; never secrets.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"prefix":{"type":"string"},"livemode":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"},"last_used_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","name","prefix","livemode","scopes","created_at","last_used_at","revoked_at"],"additionalProperties":false}}},"required":["keys"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}},"post":{"operationId":"create_customer_key","summary":"Create a named test or live key with letter scopes; secret shown once.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"livemode":{"type":"boolean"},"scopes":{"minItems":1,"maxItems":2,"type":"array","items":{"type":"string","enum":["letters:read","letters:write"]}}},"required":["name","livemode","scopes"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"secret":{"type":"string"},"prefix":{"type":"string"},"livemode":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"string"}}},"required":["id","name","secret","prefix","livemode","scopes"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/account/api-keys/{id}":{"delete":{"operationId":"revoke_customer_key","summary":"Revoke one customer API key.","x-required-scopes":[],"x-availability":"self_service","security":[{"customerSession":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-CSRF-Token","in":"header","required":true,"schema":{"type":"string"},"description":"From GET /v1/account/session; also requires a same-origin browser request."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Browser session, CSRF, validation, or account policy error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}}}}}}}}},"/v1/pricing":{"get":{"operationId":"get_pricing","summary":"Published prices, available products and limits.","x-mcp-tool":"get_pricing","x-required-scopes":[],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"effective_from":{"type":"string"},"currency":{"type":"string"},"country":{"type":"string"},"tiers":{"type":"array","items":{"type":"object","properties":{"tier":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]},"title":{"type":"string"},"description":{"type":"string"},"delivery_confirmation":{"type":"boolean","description":"False for every tier USPS does not scan at delivery. Never claim otherwise."},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."}},"required":["tier","title","description","delivery_confirmation","total"],"additionalProperties":false}},"add_ons":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"description":{"type":"string"},"unit_amount":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."}},"required":["code","description","unit_amount"],"additionalProperties":false}},"volume_pricing":{"type":"object","properties":{"applies_to":{"type":"array","items":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]}},"window":{"type":"string"},"tiers":{"type":"array","items":{"type":"object","properties":{"min_letters":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_letters":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."}},"required":["min_letters","max_letters","total"],"additionalProperties":false}}},"required":["applies_to","window","tiers"],"additionalProperties":false},"page_rules":{"type":"object","properties":{"included_pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pages_per_sheet":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"additional_ounce":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."}},"required":["included_pages","max_pages","pages_per_sheet"],"additionalProperties":false},"tax":{"type":"object","properties":{"origin_state":{"type":"string"},"note":{"type":"string"}},"required":["origin_state","note"],"additionalProperties":false}},"required":["version","effective_from","currency","country","tiers","add_ons","page_rules","tax"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/addresses/validate":{"post":{"operationId":"validate_address","summary":"Validate a US mailing address.","x-mcp-tool":"validate_address","x-required-scopes":[],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["line1","city","state","zip5"]}},"required":["address"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"deliverable":{"type":"boolean"},"address":{"anyOf":[{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip5":{"type":"string"},"zip4":{"type":"string"},"deliverable":{"type":"boolean"},"dpv":{"type":"object","properties":{"confirmed":{"type":"string","enum":["Y","N","S","D"]},"vacant":{"type":"boolean"},"cmra":{"type":"boolean"}},"required":["confirmed"],"additionalProperties":false}},"required":["line1","city","state","zip5","deliverable"],"additionalProperties":false},{"type":"null"}]},"corrections":{"type":"array","items":{"type":"string"}},"message":{"type":"string"}},"required":["deliverable","address","corrections","message"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/drafts":{"post":{"operationId":"create_draft","summary":"Create a letter draft and quote. Nothing is printed or charged.","x-mcp-tool":"create_draft","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["name","line1","city","state","zip5"]},"body":{"type":"object","properties":{"kind":{"type":"string","enum":["text","markdown","pdf"]},"content":{"type":"string","minLength":1}},"required":["kind","content"]},"tier":{"default":"standard","type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]},"colour":{"type":"boolean"},"from_address_id":{"type":"string","minLength":1},"extras":{"type":"array","items":{"type":"string","minLength":1}}},"required":["to","body"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"draft":{"type":"object","properties":{"draft_id":{"type":"string"},"livemode":{"type":"boolean"},"status":{"type":"string"},"to":{"type":"object","properties":{"name":{"type":"string"},"address":{"anyOf":[{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip5":{"type":"string"},"zip4":{"type":"string"},"deliverable":{"type":"boolean"},"dpv":{"type":"object","properties":{"confirmed":{"type":"string","enum":["Y","N","S","D"]},"vacant":{"type":"boolean"},"cmra":{"type":"boolean"}},"required":["confirmed"],"additionalProperties":false}},"required":["line1","city","state","zip5","deliverable"],"additionalProperties":false},{"type":"null"}]}},"required":["name","address"],"additionalProperties":false},"from_address_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"body_kind":{"type":"string"},"tier":{"type":"string"},"colour":{"type":"boolean"},"extras":{"type":"array","items":{"type":"string"}},"page_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"sheet_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"expires_at":{"type":"string"}},"required":["draft_id","livemode","status","to","from_address_id","body_kind","tier","colour","extras","page_count","sheet_count","created_at","updated_at","expires_at"],"additionalProperties":false},"quote":{"type":"object","properties":{"quote_id":{"type":"string","description":"Identifier for this quote, for support and receipts."},"expires_at":{"type":"string","description":"ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed."},"version":{"type":"string","description":"The published price card this total came from."},"subtotal":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"What the letter costs, before sales tax."},"tax":{"type":"object","properties":{"collected":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York."},"destination_state":{"type":"string"}},"required":["collected","destination_state"],"additionalProperties":false},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents."}},"required":["quote_id","expires_at","version","subtotal","tax","total"],"additionalProperties":false,"description":"A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents."},"note":{"type":"string"}},"required":["draft","quote","note"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/drafts/{id}":{"patch":{"operationId":"update_draft","summary":"Edit a draft and refresh its quote.","x-mcp-tool":"update_draft","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["name","line1","city","state","zip5"]},"body":{"type":"object","properties":{"kind":{"type":"string","enum":["text","markdown","pdf"]},"content":{"type":"string","minLength":1}},"required":["kind","content"]},"tier":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]},"colour":{"type":"boolean"},"from_address_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"extras":{"type":"array","items":{"type":"string","minLength":1}}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"draft":{"type":"object","properties":{"draft_id":{"type":"string"},"livemode":{"type":"boolean"},"status":{"type":"string"},"to":{"type":"object","properties":{"name":{"type":"string"},"address":{"anyOf":[{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip5":{"type":"string"},"zip4":{"type":"string"},"deliverable":{"type":"boolean"},"dpv":{"type":"object","properties":{"confirmed":{"type":"string","enum":["Y","N","S","D"]},"vacant":{"type":"boolean"},"cmra":{"type":"boolean"}},"required":["confirmed"],"additionalProperties":false}},"required":["line1","city","state","zip5","deliverable"],"additionalProperties":false},{"type":"null"}]}},"required":["name","address"],"additionalProperties":false},"from_address_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"body_kind":{"type":"string"},"tier":{"type":"string"},"colour":{"type":"boolean"},"extras":{"type":"array","items":{"type":"string"}},"page_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"sheet_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"expires_at":{"type":"string"}},"required":["draft_id","livemode","status","to","from_address_id","body_kind","tier","colour","extras","page_count","sheet_count","created_at","updated_at","expires_at"],"additionalProperties":false},"quote":{"type":"object","properties":{"quote_id":{"type":"string","description":"Identifier for this quote, for support and receipts."},"expires_at":{"type":"string","description":"ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed."},"version":{"type":"string","description":"The published price card this total came from."},"subtotal":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"What the letter costs, before sales tax."},"tax":{"type":"object","properties":{"collected":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York."},"destination_state":{"type":"string"}},"required":["collected","destination_state"],"additionalProperties":false},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents."}},"required":["quote_id","expires_at","version","subtotal","tax","total"],"additionalProperties":false,"description":"A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents."},"note":{"type":"string"}},"required":["draft","quote","note"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"operationId":"get_draft","summary":"Retrieve a draft and its stored quote.","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"draft":{"type":"object","properties":{"draft_id":{"type":"string"},"livemode":{"type":"boolean"},"status":{"type":"string"},"to":{"type":"object","properties":{"name":{"type":"string"},"address":{"anyOf":[{"type":"object","properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip5":{"type":"string"},"zip4":{"type":"string"},"deliverable":{"type":"boolean"},"dpv":{"type":"object","properties":{"confirmed":{"type":"string","enum":["Y","N","S","D"]},"vacant":{"type":"boolean"},"cmra":{"type":"boolean"}},"required":["confirmed"],"additionalProperties":false}},"required":["line1","city","state","zip5","deliverable"],"additionalProperties":false},{"type":"null"}]}},"required":["name","address"],"additionalProperties":false},"from_address_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"body_kind":{"type":"string"},"tier":{"type":"string"},"colour":{"type":"boolean"},"extras":{"type":"array","items":{"type":"string"}},"page_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"sheet_count":{"anyOf":[{"type":"number"},{"type":"null"}]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"expires_at":{"type":"string"}},"required":["draft_id","livemode","status","to","from_address_id","body_kind","tier","colour","extras","page_count","sheet_count","created_at","updated_at","expires_at"],"additionalProperties":false},"quote":{"type":"object","properties":{"quote_id":{"type":"string","description":"Identifier for this quote, for support and receipts."},"expires_at":{"type":"string","description":"ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed."},"version":{"type":"string","description":"The published price card this total came from."},"subtotal":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"What the letter costs, before sales tax."},"tax":{"type":"object","properties":{"collected":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York."},"destination_state":{"type":"string"}},"required":["collected","destination_state"],"additionalProperties":false},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents."}},"required":["quote_id","expires_at","version","subtotal","tax","total"],"additionalProperties":false,"description":"A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents."},"note":{"type":"string"}},"required":["draft","quote","note"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/drafts/{id}/preview":{"get":{"operationId":"preview_draft","summary":"Review the PDF, current total and mailing requirements before approval.","x-mcp-tool":"preview_draft","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"preview_url":{"type":"string","description":"A time-limited link to the exact PDF that will be printed. Give it to the user; it dies with the draft."},"page_count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tier":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"],"description":"The product this draft is priced as, as passed to create_draft."},"tier_title":{"type":"string","description":"What the price card in force calls that product, such as Standard. Use this name when you tell the user what they are buying."},"included_pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Printed pages the headline price covers. This draft is priced at that total up to this many pages."},"quote":{"type":"object","properties":{"quote_id":{"type":"string","description":"Identifier for this quote, for support and receipts."},"expires_at":{"type":"string","description":"ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed."},"version":{"type":"string","description":"The published price card this total came from."},"subtotal":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"What the letter costs, before sales tax."},"tax":{"type":"object","properties":{"collected":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York."},"destination_state":{"type":"string"}},"required":["collected","destination_state"],"additionalProperties":false},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents."}},"required":["quote_id","expires_at","version","subtotal","tax","total"],"additionalProperties":false,"description":"A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents."},"expires_at":{"type":"string"},"requirements":{"type":"array","items":{"type":"string"},"description":"What the user is agreeing to: how USPS requires the envelope to be printed, and what this particular letter is. State these to the user before calling send_letter."}},"required":["draft_id","preview_url","page_count","tier","tier_title","included_pages","quote","expires_at","requirements"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/letters":{"post":{"operationId":"send_letter","summary":"Create one order for an approved draft and exact total. Reuse idempotency_key on retries.","x-mcp-tool":"send_letter","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string","minLength":1},"confirm_total_cents":{"type":"integer","minimum":0,"maximum":9007199254740991},"idempotency_key":{"type":"string","minLength":1}},"required":["draft_id","confirm_total_cents","idempotency_key"]}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"letter_id":{"type":"string"},"order_id":{"type":"string"},"status":{"type":"string","enum":["pending_payment","pending_moderation","held_for_review","queued","printed","postage_applied","accepted_by_usps","in_transit","arrived_at_destination_facility","expected_delivery","delivered","blocked","cancelled","payment_abandoned","returned"],"description":"Where the letter is. expected_delivery is the last state a standard or proof-of-mailing letter reaches; only certified tiers ever reach delivered."},"checkout_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"payment_url":{"type":"string"},"quote":{"type":"object","properties":{"quote_id":{"type":"string","description":"Identifier for this quote, for support and receipts."},"expires_at":{"type":"string","description":"ISO 8601 instant after which this total is re-computed from the live price card. Call preview_draft for a fresh quote before sending if it has passed."},"version":{"type":"string","description":"The published price card this total came from."},"subtotal":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"What the letter costs, before sales tax."},"tax":{"type":"object","properties":{"collected":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"New York sales tax on this letter. We mail from New York, so a few cents apply wherever the letter goes, and more when it is going to New York."},"destination_state":{"type":"string"}},"required":["collected","destination_state"],"additionalProperties":false},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"Subtotal plus sales tax. This is the number send_letter requires in confirm_total_cents."}},"required":["quote_id","expires_at","version","subtotal","tax","total"],"additionalProperties":false,"description":"A priced letter. State total.display to the user before sending, and pass total.amount_cents as confirm_total_cents."},"mail_date_estimate":{"type":"string"},"message":{"type":"string"}},"required":["letter_id","order_id","status","checkout_url","quote","mail_date_estimate","message"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"operationId":"list_letters","summary":"List letters with cursor pagination.","x-mcp-tool":"list_letters","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"starting_after","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"letters":{"type":"array","items":{"type":"object","properties":{"letter_id":{"type":"string"},"status":{"type":"string","enum":["pending_payment","pending_moderation","held_for_review","queued","printed","postage_applied","accepted_by_usps","in_transit","arrived_at_destination_facility","expected_delivery","delivered","blocked","cancelled","payment_abandoned","returned"],"description":"Where the letter is. expected_delivery is the last state a standard or proof-of-mailing letter reaches; only certified tiers ever reach delivered."},"tier":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]},"created_at":{"type":"string"},"mail_date":{"type":"string"},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."},"destination_state":{"type":"string"}},"required":["letter_id","status","tier","created_at","mail_date","total","destination_state"],"additionalProperties":false}},"has_more":{"type":"boolean"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["letters","has_more","next_cursor"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/letters/{id}":{"get":{"operationId":"get_letter_status","summary":"Read payment, mailing status, scans and delivery estimates.","x-mcp-tool":"get_letter_status","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"tracking_number":{"description":"USPS Certified Mail tracking number, present once the operator saves it.","type":"string"},"tracking_url":{"description":"Direct USPS tracking link. Share it with the user when available.","type":"string"},"letter_id":{"type":"string"},"livemode":{"type":"boolean","description":"False for sandbox letters, which are never mailed."},"tier":{"type":"string","enum":["standard","proof_of_mailing","certified","certified_err","registered"]},"status":{"type":"string","enum":["pending_payment","pending_moderation","held_for_review","queued","printed","postage_applied","accepted_by_usps","in_transit","arrived_at_destination_facility","expected_delivery","delivered","blocked","cancelled","payment_abandoned","returned"],"description":"Where the letter is. expected_delivery is the last state a standard or proof-of-mailing letter reaches; only certified tiers ever reach delivered."},"description":{"type":"string","description":"One sentence for the user about where this letter is."},"mail_date":{"type":"string","description":"The calendar date (YYYY-MM-DD, New York time) this piece goes to USPS."},"expected_delivery_estimate":{"anyOf":[{"type":"object","properties":{"earliest":{"type":"string"},"latest":{"type":"string"}},"required":["earliest","latest"],"additionalProperties":false,"description":"The window (YYYY-MM-DD, New York time) USPS is expected to deliver in. USPS does not scan plain letters at delivery, so this is an estimate and never a confirmation."},{"type":"null"}]},"delivery_confirmation":{"type":"boolean","description":"False for every tier USPS does not scan at delivery. Never claim otherwise."},"delivered_at":{"description":"Certified tiers only, and absent entirely for the tiers USPS does not scan.","anyOf":[{"type":"string"},{"type":"null"}]},"disclosure":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Say this to the user whenever an expected delivery date is shown."},"scans":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The USPS processing phase this scan came from, 0 through 4."},"scanned_at":{"type":"string"},"description":{"type":"string"}},"required":["phase","scanned_at","description"],"additionalProperties":false}},"created_at":{"type":"string"},"cancelled_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"payment":{"type":"object","properties":{"order_id":{"type":"string"},"order_status":{"type":"string","enum":["pending","awaiting_payment","paid","failed","refunded","disputed","abandoned"]},"paid_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"payment_url":{"type":"string"},"total":{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The amount in whole US cents."},"currency":{"type":"string","const":"USD"},"display":{"type":"string","description":"The amount formatted for a person, with a currency symbol."}},"required":["amount_cents","currency","display"],"additionalProperties":false,"description":"An amount of money. Always read amount_cents; display is for showing the user."},"checkout_url":{"description":"Present only while the letter is waiting for payment. Give it to the user.","type":"string"}},"required":["order_id","order_status","paid_at","total"],"additionalProperties":false}},"required":["letter_id","livemode","tier","status","description","mail_date","expected_delivery_estimate","delivery_confirmation","disclosure","scans","created_at","cancelled_at","payment"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/letters/{id}/checkout":{"post":{"operationId":"complete_checkout","summary":"Pay the existing letter with a shared payment token. An empty body requests an MPP challenge; use Payment-Authorization for its credential.","x-mcp-tool":"complete_checkout","x-required-scopes":["letters:write"],"x-availability":"programmatic_payment","security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Payment-Authorization","in":"header","required":false,"schema":{"type":"string"},"description":"MPP Payment credential containing the approved shared payment token. Preserve your OAuth/API-key authentication."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"shared_payment_token":{"type":"string","minLength":1,"maxLength":4096},"token_constraints":{"type":"object","properties":{"amount_limit_cents":{"description":"The most the token may be charged, in US cents.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"expires_at":{"description":"Unix seconds after which the token can no longer be spent.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"seller":{"description":"The seller the token is scoped to.","type":"string"}}}},"additionalProperties":false}}}},"responses":{"200":{"description":"The existing order is paid, including an idempotent replay.","headers":{"Payment-Receipt":{"schema":{"type":"string"},"description":"MPP payment receipt when a Payment-Authorization credential settled or replayed a payment intent."}},"content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string"},"letter_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"order_status":{"type":"string","enum":["pending","awaiting_payment","paid","failed","refunded","disputed","abandoned"],"description":"`paid` means the money moved and the letter is released to print."},"payment_intent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The payment record at the provider, for the user’s receipt questions."},"already_paid":{"type":"boolean","description":"True when this order was already paid, so this call charged nothing."},"message":{"type":"string","description":"What to tell the user. Read it before answering."}},"required":["order_id","letter_id","order_status","payment_intent_id","already_paid","message"],"additionalProperties":false}}}},"400":{"description":"Invalid input or payment credential.","content":{"application/problem+json":{"schema":{"type":"object","required":["type","title","status","code","detail"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"detail":{"type":"string"},"checkout_url":{"type":"string"}}}},"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Approve the exact order payment and retry the same request. Available only with the matching Stripe profile and payment configuration.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"description":"MPP Payment challenge; credential header is Payment-Authorization."}},"content":{"application/problem+json":{"schema":{"type":"object","properties":{"status":{"type":"integer"},"code":{"type":"string"},"detail":{"type":"string"},"checkout_url":{"type":"string"}}}}}},"409":{"description":"Payment is unresolved or the order is no longer payable.","content":{"application/problem+json":{"schema":{"type":"object","required":["type","title","status","code","detail"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"detail":{"type":"string"},"checkout_url":{"type":"string"}}}},"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"The matching payment configuration is unavailable.","content":{"application/problem+json":{"schema":{"type":"object","required":["type","title","status","code","detail"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string"},"detail":{"type":"string"},"checkout_url":{"type":"string"}}}},"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/account":{"get":{"operationId":"get_account","summary":"Read the connected account and credential mode.","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string"},"email":{"type":"string"},"entity_name":{"type":"string"},"kyc_status":{"type":"string"},"volume_tier":{"type":"number"},"livemode":{"type":"boolean"},"created_at":{"type":"string"}},"required":["account_id","email","entity_name","kyc_status","volume_tier","livemode","created_at"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/account/notifications":{"get":{"operationId":"get_notifications","summary":"Read email preferences; settings apply across both modes.","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"notifications":{"type":"array","items":{"type":"object","properties":{"notification":{"type":"string"},"enabled":{"type":"boolean"},"chosen":{"type":"boolean"},"description":{"type":"string"}},"required":["notification","enabled","chosen","description"],"additionalProperties":false}}},"required":["notifications"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"operationId":"set_notification","summary":"Change one email preference.","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"notification":{"type":"string","minLength":1},"enabled":{"type":"boolean"}},"required":["notification","enabled"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"notifications":{"type":"array","items":{"type":"object","properties":{"notification":{"type":"string"},"enabled":{"type":"boolean"},"chosen":{"type":"boolean"},"description":{"type":"string"}},"required":["notification","enabled","chosen","description"],"additionalProperties":false}}},"required":["notifications"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/webhook_endpoints":{"post":{"operationId":"create_webhook_endpoint","summary":"Subscribe an HTTPS endpoint; the signing secret is returned only once.","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1},"events":{"minItems":1,"type":"array","items":{"type":"string","minLength":1}}},"required":["url","events"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"livemode":{"type":"boolean"},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutive_failures":{"type":"number"},"created_at":{"type":"string"},"secret":{"type":"string"}},"required":["id","url","events","active","livemode","disabled_reason","consecutive_failures","created_at","secret"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"get":{"operationId":"list_webhook_endpoints","summary":"List webhook subscriptions.","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"webhook_endpoints":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"livemode":{"type":"boolean"},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutive_failures":{"type":"number"},"created_at":{"type":"string"}},"required":["id","url","events","active","livemode","disabled_reason","consecutive_failures","created_at"],"additionalProperties":false}}},"required":["webhook_endpoints"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/webhook_endpoints/{id}":{"get":{"operationId":"get_webhook_endpoint","summary":"Read a webhook subscription.","x-required-scopes":["letters:read"],"security":[{"oauth":["letters:read"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"livemode":{"type":"boolean"},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutive_failures":{"type":"number"},"created_at":{"type":"string"}},"required":["id","url","events","active","livemode","disabled_reason","consecutive_failures","created_at"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"patch":{"operationId":"update_webhook_endpoint","summary":"Update a webhook subscription.","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1},"events":{"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"livemode":{"type":"boolean"},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutive_failures":{"type":"number"},"created_at":{"type":"string"}},"required":["id","url","events","active","livemode","disabled_reason","consecutive_failures","created_at"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"delete":{"operationId":"delete_webhook_endpoint","summary":"Delete a webhook subscription.","x-required-scopes":["letters:write"],"security":[{"oauth":["letters:write"]},{"apiKey":[]},{"bearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/abuse-reports":{"post":{"operationId":"report_abuse","summary":"Report unwanted mail. Responses do not reveal recipient history.","x-required-scopes":[],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"recipient_address":{"type":"object","properties":{"name":{"type":"string","minLength":1},"line1":{"type":"string","minLength":1},"line2":{"type":"string"},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":2,"maxLength":2},"zip5":{"type":"string","pattern":"^\\d{5}$"},"zip4":{"type":"string","pattern":"^\\d{4}$"}},"required":["line1","city","state","zip5"]},"reason":{"type":"string","minLength":1,"maxLength":1000}},"required":["recipient_address"]}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["accepted","message"],"additionalProperties":false}}}},"default":{"description":"A stable error code and actionable message. 401: authenticate; 403: permission or policy; 404: unavailable object; 409: conflict; 422: domain refusal; 429: quota; 5xx: retry or contact support.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before a quota retry."}},"content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/oauth/device_authorization":{"post":{"operationId":"device_authorization","security":[],"summary":"Start a customer-approved agent connection (when self-service is enabled).","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"client_id":{"type":"string"},"scope":{"type":"string"},"resource":{"type":"string"}},"required":["client_id"]}},"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string"},"scope":{"type":"string"},"resource":{"type":"string"}},"required":["client_id"]}}}},"responses":{"200":{"description":"Device code and browser link.","content":{"application/json":{"schema":{"type":"object","required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"properties":{"device_code":{"type":"string"},"user_code":{"type":"string"},"verification_uri":{"type":"string"},"verification_uri_complete":{"type":"string"},"expires_in":{"type":"integer","const":600},"interval":{"type":"integer","const":5}}}}}},"400":{"description":"OAuth error: authorization_pending, slow_down, access_denied, expired_token, invalid_grant, or invalid_scope. Device codes expire in 600 seconds; poll every 5 seconds, adding 5 on slow_down."}}}},"/oauth/register":{"post":{"operationId":"register_oauth_client","security":[],"summary":"Register a public client. Redirect-free registration requires explicit device_code grant.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"const":"none"},"scope":{"type":"string"}},"required":[]}},"application/json":{"schema":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"const":"none"},"scope":{"type":"string"}},"required":[]}}}},"responses":{"201":{"description":"Client metadata and client_id. No client secret."},"400":{"description":"Invalid client metadata."}}}},"/oauth/token":{"post":{"operationId":"oauth_token","security":[],"summary":"Redeem an authorization/device code or rotate a refresh token.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"grant_type":{"type":"string"},"client_id":{"type":"string"},"device_code":{"type":"string"},"code":{"type":"string"},"redirect_uri":{"type":"string"},"code_verifier":{"type":"string"},"refresh_token":{"type":"string"},"scope":{"type":"string"},"resource":{"type":"string"}},"required":["grant_type"]}},"application/json":{"schema":{"type":"object","properties":{"grant_type":{"type":"string"},"client_id":{"type":"string"},"device_code":{"type":"string"},"code":{"type":"string"},"redirect_uri":{"type":"string"},"code_verifier":{"type":"string"},"refresh_token":{"type":"string"},"scope":{"type":"string"},"resource":{"type":"string"}},"required":["grant_type"]}}}},"responses":{"200":{"description":"One-hour PaperAgent access token and rotating 30-day refresh token.","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"token_type":{"const":"Bearer"},"expires_in":{"type":"integer","const":3600},"scope":{"type":"string"}}}}}},"400":{"description":"OAuth error: authorization_pending, slow_down, access_denied, expired_token, invalid_grant, or invalid_scope. Device codes expire in 600 seconds; poll every 5 seconds, adding 5 on slow_down."}}}}},"components":{"securitySchemes":{"customerSession":{"type":"apiKey","in":"cookie","name":"__Host-pa_session","description":"Google-authenticated browser session only. Bearer tokens and API keys cannot manage credentials. Mutations require Origin and X-CSRF-Token."},"apiKey":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"PaperAgent sk_live_ or sk_test_ key, never a Stripe key."},"bearer":{"type":"http","scheme":"bearer","description":"PaperAgent API key or OAuth access token."},"oauth":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://paperagent.dev/oauth/authorize","tokenUrl":"https://paperagent.dev/oauth/token","scopes":{"letters:read":"Read letters and previews","letters:write":"Create drafts, authorize payments and manage account preferences"}}}}}},"externalDocs":{"url":"https://paperagent.dev/docs"}}