Turn a private cAROUSD transfer into a mailable letter. Escrows
amount from a custodial wallet into the Aro Mail vault (a
confidentialTransfer to the platform operator) and returns the
letter with its one-time claimCode, the claimUrl the QR encodes
(https://<aropay-host>/claim#<code>, code in the URL fragment), and
the pdfUrl of the printable page.
Defaults depend on the destination: domestic letters (destination =
the deployment’s home country, US by default) are visible and
expire in 90 days; international letters are sealed and expire in
45 days. Addresses follow the destination’s rules (US: two-letter
state, ZIP or ZIP+4, 64-character lines; elsewhere region or
postal is required). Amounts above the per-letter cap return
400 invalid_amount; too many letters in flight return
429 letter_velocity_limit.
Blocks up to ~20 s for the escrow receipt. A letter returned as
DRAFT with a PENDING escrow leg becomes ESCROWED on a later read
once the receipt lands and the encrypted amount is verified; a
reverted or clamped escrow becomes FAILED with nothing moved. If the
escrow was broadcast but the bookkeeping after it failed, the call
returns 502 escrow_unsettled instead of the letter: the letter
exists as DRAFT (find it in GET /transfer/letter), value has left
the wallet, and reconciliation finishes it on the next read. Do not
create it again.
claimCode and claimUrl are returned only here and on
GET /transfer/letter/{id}, only to the owner, and only while the
letter is not terminal. Anyone holding the code can claim once.
AroPay API key, sent as Authorization: Bearer aro_sk_…. Created in
the dashboard under Settings → API keys. Takes precedence over a
session cookie when both are present.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"AroPay","description":"AroPay: sealed, private payments on public ledgers, built on the Aro Confidential Rails with Zama Protocol FHE. Production runs on Ethereum Mainnet; a Sepolia sandbox is available for integration.","colors":{"primary":"#8A7C63","light":"#C9BA97","dark":"#6E6148"},"logo":{"light":"https://mintcdn.com/aro-pay/KNYEWxjVGo5XgIrA/logo/light.svg?fit=max\u0026auto=format\u0026n=KNYEWxjVGo5XgIrA\u0026q=85\u0026s=bb49753238a5be47e146c889187987bc","dark":"https://mintcdn.com/aro-pay/KNYEWxjVGo5XgIrA/logo/dark.svg?fit=max\u0026auto=format\u0026n=KNYEWxjVGo5XgIrA\u0026q=85\u0026s=2c28e76d437217e38fd491d063dd2dd2","href":"https://aropay.aro.media"},"favicon":"https://mintcdn.com/aro-pay/KNYEWxjVGo5XgIrA/favicon.svg?fit=max\u0026auto=format\u0026n=KNYEWxjVGo5XgIrA\u0026q=85\u0026s=3f6196676055cb57c334a72d26f1756d","api":{"playground":{"display":"interactive"},"examples":{"defaults":"required","languages":["curl","javascript","python"]}},"appearance":{"default":"system"},"background":{"color":{"light":"#F5F3EF","dark":"#17140F"}},"navbar":{"links":[{"href":"https://aropay.aro.media","label":"Dashboard"}],"primary":{"type":"button","label":"Open sandbox","href":"https://dev.aropay.aro.media"}},"footer":{"socials":{"website":"https://aro.media"}},"search":{"prompt":"Search AroPay docs…"},"seo":{"metatags":{"og:site_name":"AroPay Documentation"}},"fonts":{"family":"IBM Plex Sans"},"styling":{"codeblocks":"system","latex":false},"contextual":{"options":["copy","view","chatgpt","claude","cursor"],"display":"header"},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"aro-pay","hasAudioNarration":false,"actualSubdomain":"aro-pay","customDomains":["docs.aropay.aro.media"],"gitSource":{"type":"github","owner":"aromediainc","repo":"aromedia-admin-portal","deployBranch":"main","contentDirectory":"docs/aropay","isPrivate":true,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6ae282992f009a079b89912f","collectionId":"3d1e538a-3ee1-4c54-b928-210befac466d","liveDeploymentHistoryId":"6ae282992f009a079b89912f","schemaVersion":"v3"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae282992f009a079b89912f","clientVersion":"0.0.4044","searchFilterCounts":[{"language":"default","tag":"API reference","count":48},{"language":"default","tag":"Documentation","count":24},{"language":"default","tag":"Profile \u0026 security","count":12},{"language":"default","tag":"Aro Mail","count":9},{"language":"default","tag":"Core concepts","count":7},{"language":"default","tag":"Guides","count":7},{"language":"default","tag":"Security \u0026 access","count":7},{"language":"default","tag":"Auth","count":6},{"language":"default","tag":"Wallets","count":5},{"language":"default","tag":"Money movement","count":4}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[],"page":{"pagePath":"api-reference/aro-mail/create-letter","slug":"/api-reference/aro-mail/create-letter","pageMetadata":{"title":"Create letter","description":"Turn a private cAROUSD transfer into a mailable letter. Escrows\n`amount` from a **custodial** wallet into the Aro Mail vault (a\n`confidentialTransfer` to the platform operator) and returns the\nletter with its one-time `claimCode`, the `claimUrl` the QR encodes\n(`https://\u003caropay-host>/claim#\u003ccode>`, code in the URL fragment), and\nthe `pdfUrl` of the printable page.\n\nDefaults depend on the destination: domestic letters (destination =\nthe deployment's home country, `US` by default) are `visible` and\nexpire in 90 days; international letters are `sealed` and expire in\n45 days. Addresses follow the destination's rules (US: two-letter\nstate, ZIP or ZIP+4, 64-character lines; elsewhere `region` or\n`postal` is required). Amounts above the per-letter cap return\n`400 invalid_amount`; too many letters in flight return\n`429 letter_velocity_limit`.\n\nBlocks up to ~20 s for the escrow receipt. A letter returned as\n`DRAFT` with a `PENDING` escrow leg becomes `ESCROWED` on a later read\nonce the receipt lands **and** the encrypted amount is verified; a\nreverted or clamped escrow becomes `FAILED` with nothing moved. If the\nescrow was broadcast but the bookkeeping after it failed, the call\nreturns `502 escrow_unsettled` instead of the letter: the letter\nexists as `DRAFT` (find it in `GET /transfer/letter`), value has left\nthe wallet, and reconciliation finishes it on the next read. Do not\ncreate it again.\n\n`claimCode` and `claimUrl` are returned only here and on\n`GET /transfer/letter/{id}`, only to the owner, and only while the\nletter is not terminal. Anyone holding the code can claim once.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter","href":"/api-reference/aro-mail/create-letter","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n strong: \"strong\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Turn a private cAROUSD transfer into a mailable letter. Escrows\\n\", _jsx(_components.code, {\n children: \"amount\"\n }), \" from a \", _jsx(_components.strong, {\n children: \"custodial\"\n }), \" wallet into the Aro Mail vault (a\\n\", _jsx(_components.code, {\n children: \"confidentialTransfer\"\n }), \" to the platform operator) and returns the\\nletter with its one-time \", _jsx(_components.code, {\n children: \"claimCode\"\n }), \", the \", _jsx(_components.code, {\n children: \"claimUrl\"\n }), \" the QR encodes\\n(\", _jsx(_components.code, {\n children: \"https://\u003caropay-host>/claim#\u003ccode>\"\n }), \", code in the URL fragment), and\\nthe \", _jsx(_components.code, {\n children: \"pdfUrl\"\n }), \" of the printable page.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Defaults depend on the destination: domestic letters (destination =\\nthe deployment’s home country, \", _jsx(_components.code, {\n children: \"US\"\n }), \" by default) are \", _jsx(_components.code, {\n children: \"visible\"\n }), \" and\\nexpire in 90 days; international letters are \", _jsx(_components.code, {\n children: \"sealed\"\n }), \" and expire in\\n45 days. Addresses follow the destination’s rules (US: two-letter\\nstate, ZIP or ZIP+4, 64-character lines; elsewhere \", _jsx(_components.code, {\n children: \"region\"\n }), \" or\\n\", _jsx(_components.code, {\n children: \"postal\"\n }), \" is required). Amounts above the per-letter cap return\\n\", _jsx(_components.code, {\n children: \"400 invalid_amount\"\n }), \"; too many letters in flight return\\n\", _jsx(_components.code, {\n children: \"429 letter_velocity_limit\"\n }), \".\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Blocks up to ~20 s for the escrow receipt. A letter returned as\\n\", _jsx(_components.code, {\n children: \"DRAFT\"\n }), \" with a \", _jsx(_components.code, {\n children: \"PENDING\"\n }), \" escrow leg becomes \", _jsx(_components.code, {\n children: \"ESCROWED\"\n }), \" on a later read\\nonce the receipt lands \", _jsx(_components.strong, {\n children: \"and\"\n }), \" the encrypted amount is verified; a\\nreverted or clamped escrow becomes \", _jsx(_components.code, {\n children: \"FAILED\"\n }), \" with nothing moved. If the\\nescrow was broadcast but the bookkeeping after it failed, the call\\nreturns \", _jsx(_components.code, {\n children: \"502 escrow_unsettled\"\n }), \" instead of the letter: the letter\\nexists as \", _jsx(_components.code, {\n children: \"DRAFT\"\n }), \" (find it in \", _jsx(_components.code, {\n children: \"GET /transfer/letter\"\n }), \"), value has left\\nthe wallet, and reconciliation finishes it on the next read. Do not\\ncreate it again.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.code, {\n children: \"claimCode\"\n }), \" and \", _jsx(_components.code, {\n children: \"claimUrl\"\n }), \" are returned only here and on\\n\", _jsx(_components.code, {\n children: \"GET /transfer/letter/{id}\"\n }), \", only to the owner, and only while the\\nletter is not terminal. Anyone holding the code can claim once.\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"codeStyling":"system","config":{},"pageMetadata":{"title":"Create letter","description":"Turn a private cAROUSD transfer into a mailable letter. Escrows\n`amount` from a **custodial** wallet into the Aro Mail vault (a\n`confidentialTransfer` to the platform operator) and returns the\nletter with its one-time `claimCode`, the `claimUrl` the QR encodes\n(`https://\u003caropay-host>/claim#\u003ccode>`, code in the URL fragment), and\nthe `pdfUrl` of the printable page.\n\nDefaults depend on the destination: domestic letters (destination =\nthe deployment's home country, `US` by default) are `visible` and\nexpire in 90 days; international letters are `sealed` and expire in\n45 days. Addresses follow the destination's rules (US: two-letter\nstate, ZIP or ZIP+4, 64-character lines; elsewhere `region` or\n`postal` is required). Amounts above the per-letter cap return\n`400 invalid_amount`; too many letters in flight return\n`429 letter_velocity_limit`.\n\nBlocks up to ~20 s for the escrow receipt. A letter returned as\n`DRAFT` with a `PENDING` escrow leg becomes `ESCROWED` on a later read\nonce the receipt lands **and** the encrypted amount is verified; a\nreverted or clamped escrow becomes `FAILED` with nothing moved. If the\nescrow was broadcast but the bookkeeping after it failed, the call\nreturns `502 escrow_unsettled` instead of the letter: the letter\nexists as `DRAFT` (find it in `GET /transfer/letter`), value has left\nthe wallet, and reconciliation finishes it on the next read. Do not\ncreate it again.\n\n`claimCode` and `claimUrl` are returned only here and on\n`GET /transfer/letter/{id}`, only to the owner, and only while the\nletter is not terminal. Anyone holding the code can claim once.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter","href":"/api-reference/aro-mail/create-letter","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"operationId":"createLetter","tags":["Aro Mail"],"summary":"Create letter","description":"Turn a private cAROUSD transfer into a mailable letter. Escrows\n`amount` from a **custodial** wallet into the Aro Mail vault (a\n`confidentialTransfer` to the platform operator) and returns the\nletter with its one-time `claimCode`, the `claimUrl` the QR encodes\n(`https://\u003caropay-host>/claim#\u003ccode>`, code in the URL fragment), and\nthe `pdfUrl` of the printable page.\n\nDefaults depend on the destination: domestic letters (destination =\nthe deployment's home country, `US` by default) are `visible` and\nexpire in 90 days; international letters are `sealed` and expire in\n45 days. Addresses follow the destination's rules (US: two-letter\nstate, ZIP or ZIP+4, 64-character lines; elsewhere `region` or\n`postal` is required). Amounts above the per-letter cap return\n`400 invalid_amount`; too many letters in flight return\n`429 letter_velocity_limit`.\n\nBlocks up to ~20 s for the escrow receipt. A letter returned as\n`DRAFT` with a `PENDING` escrow leg becomes `ESCROWED` on a later read\nonce the receipt lands **and** the encrypted amount is verified; a\nreverted or clamped escrow becomes `FAILED` with nothing moved. If the\nescrow was broadcast but the bookkeeping after it failed, the call\nreturns `502 escrow_unsettled` instead of the letter: the letter\nexists as `DRAFT` (find it in `GET /transfer/letter`), value has left\nthe wallet, and reconciliation finishes it on the next read. Do not\ncreate it again.\n\n`claimCode` and `claimUrl` are returned only here and on\n`GET /transfer/letter/{id}`, only to the owner, and only while the\nletter is not terminal. Anyone holding the code can claim once.\n","requestBody":"068d2978-9aa6-494f-bb1b-c9b78ffb1936","responses":{"201":"682b4194-f6ee-485c-b523-6955a31158d2","400":"b4b1b956-6631-4c31-98b8-afa2fd38fd29","401":"bae16558-a997-40c6-96df-1cb19640066f","403":"3b882d8e-287c-413d-a45f-092fa40594de","404":"ce341672-2297-4692-919d-fd82677d9590","429":"3564ac7b-e195-42b9-9cc4-1c04250e7ade","500":"b47281f3-1fe4-4009-9ec9-fa489c9ab647","502":"29aaff0d-d0e2-4a9a-b5e3-30fd87ab8baa","503":"b42729b2-61e8-491a-9218-4a7f08419181"},"method":"post","type":"path","servers":["c837b5b6-f6c5-4ad6-b620-ca1cf2cae4a7","df7e7bea-be31-4d3d-843d-dfab99bc94be","ac04ba04-2f66-410d-9f9f-c4f321306820"],"security":["06894aaa-108e-4956-bd1d-30d99fa0783d","47f3af7a-6853-48a9-8cc8-9b180c45a9ab"],"path":"/transfer/letter","baseUrlOptions":["https://aropay.aro.media/api/v1","https://dev.aropay.aro.media/api/v1","http://aropay.localhost:3000/api/v1"],"title":"Create letter","codeSamples":[],"requestExampleLanguages":["bash","javascript","python"],"requiredOnlyExamples":true,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["walletId","amount","recipient"],"properties":{"walletId":{"type":"string","description":"Sending wallet; must be custodial and hold enough cAROUSD.","isRequired":true,"uniqueKey":"walletId","typeLabel":"string"},"amount":{"type":"string","description":"Decimal string in human units, up to the deployment's per-letter cap (default 10,000).","examples":["50"],"isRequired":true,"uniqueKey":"amount","typeLabel":"string"},"recipient":{"type":"object","required":["name","address"],"properties":{"name":{"type":"string","minLength":1,"maxLength":40,"description":"Printed on the letter and used as Lob's `to.name`.","isRequired":true,"uniqueKey":"recipient.name","typeLabel":"string"},"address":{"type":"object","description":"Recipient postal address as submitted. `country` is ISO 3166-1\nalpha-2 (case-insensitive). Empty strings are treated as absent.\nField lengths are Lob's verified input limits.\n","required":["line1","city","country"],"properties":{"line1":{"type":"string","minLength":1,"maxLength":200,"description":"Street line. At most 64 characters for US addresses.","isRequired":true,"uniqueKey":"recipient.address.line1","typeLabel":"string"},"city":{"type":"string","minLength":1,"maxLength":200,"isRequired":true,"uniqueKey":"recipient.address.city","typeLabel":"string"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO 3166-1 alpha-2 country code, e.g. `NG`. Must not be on the deployment's block list.","examples":["NG"],"isRequired":true,"uniqueKey":"recipient.address.country","typeLabel":"string"},"line2":{"type":"string","maxLength":200,"description":"Optional second line (apartment, district). At most 64 characters for US addresses.","uniqueKey":"recipient.address.line2","typeLabel":"string"},"landmark":{"type":"string","maxLength":100,"description":"Optional nearby landmark, printed as its own `Near …` line. It is\nfolded into the second address line for Lob, so `line2 + landmark`\nmust fit the destination's limit (64 US / 200 international).\n","uniqueKey":"recipient.address.landmark","typeLabel":"string"},"region":{"type":"string","maxLength":200,"description":"State, province or region. US: required two-letter state or\nterritory code. Elsewhere: free text (ISO 3166-2 code or local\nname); either `region` or `postal` is required.\n","uniqueKey":"recipient.address.region","typeLabel":"string"},"postal":{"type":"string","maxLength":40,"description":"Postal code. US: required ZIP or ZIP+4. Elsewhere: optional when\n`region` is present.\n","uniqueKey":"recipient.address.postal","typeLabel":"string"}},"isRequired":true,"uniqueKey":"recipient.address","typeLabel":"object"}},"isRequired":true,"uniqueKey":"recipient","typeLabel":"object"},"memo":{"type":"string","maxLength":200,"description":"Optional note printed on the letter (hidden from the public preview for sealed letters).","uniqueKey":"memo","typeLabel":"string"},"amountVisibility":{"type":"string","enum":["sealed","visible"],"description":"Defaults to `visible` for domestic letters and `sealed` for international ones.","uniqueKey":"amountVisibility","typeLabel":"enum\u003cstring>"},"expiresInDays":{"type":"integer","minimum":1,"maximum":180,"description":"Defaults to 90 (domestic) or 45 (international). Unclaimed letters refund the sender at expiry.","uniqueKey":"expiresInDays","typeLabel":"integer"}},"uniqueKey":"","typeLabel":"object"},"example":{"walletId":"ckwlt0001abcd","amount":"50","recipient":{"name":"Jane Doe","address":{"line1":"12 Adeola Odeku Street","line2":"Victoria Island","landmark":"Opposite Eko Hotel","city":"Lagos","region":"LA","country":"NG"}},"memo":"Thanks for the referral","amountVisibility":"sealed","expiresInDays":45},"examples":{"Example":{"title":"Example","value":{"walletId":"ckwlt0001abcd","amount":"50","recipient":{"name":"Jane Doe","address":{"line1":"12 Adeola Odeku Street","line2":"Victoria Island","landmark":"Opposite Eko Hotel","city":"Lagos","region":"LA","country":"NG"}},"memo":"Thanks for the referral","amountVisibility":"sealed","expiresInDays":45}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"682b4194-f6ee-485c-b523-6955a31158d2":{"description":"The letter, normally `ESCROWED` with a verified escrow leg.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"data":{"type":"object","required":["letter"],"properties":{"letter":{"type":"object","description":"An Aro Mail letter: escrowed cAROUSD, a recipient address, a one-time\nclaim code, and the legs that moved value.\n","required":["id","status","chainId","amount","token","amountVisibility","memo","recipient","isDomestic","expiresAt","sender","claimCode","claimUrl","pdfUrl","escrow","claim","refund","mail","needsReview","error","createdAt","updatedAt"],"properties":{"id":{"type":"string","examples":["cklet0001abcd"],"isRequired":true,"uniqueKey":"data.letter.id","typeLabel":"string"},"status":{"type":"string","enum":["DRAFT","ESCROWED","MAILED","CLAIMING","CLAIMED","EXPIRED","VOIDED","FAILED"],"description":"`DRAFT` (escrow submitted) → `ESCROWED` (escrow verified) →\noptional `MAILED` → `CLAIMING` → `CLAIMED`. `EXPIRED` and `VOIDED`\ncarry a refund leg. `FAILED` means the escrow reverted, clamped or\nwas never submitted: no value left the sender. Claimable:\n`ESCROWED`, `MAILED`. Terminal: `CLAIMED`, `EXPIRED`, `VOIDED`,\n`FAILED`.\n","isRequired":true,"uniqueKey":"data.letter.status","typeLabel":"enum\u003cstring>"},"chainId":{"type":"integer","examples":[11155111],"isRequired":true,"uniqueKey":"data.letter.chainId","typeLabel":"integer"},"amount":{"type":"string","description":"Decimal string in human units. Cleartext to the parties; encrypted on-chain.","isRequired":true,"uniqueKey":"data.letter.amount","typeLabel":"string"},"token":{"type":"string","examples":["cAROUSD"],"isRequired":true,"uniqueKey":"data.letter.token","typeLabel":"string"},"amountVisibility":{"type":"string","enum":["sealed","visible"],"description":"Whether the printed letter shows the amount. Defaults to `visible` domestic, `sealed` international.","isRequired":true,"uniqueKey":"data.letter.amountVisibility","typeLabel":"enum\u003cstring>"},"memo":{"oneOf":[{"type":"string","description":"Up to 200 characters, printed on the letter.","isRequired":true,"uniqueKey":"data.letter.memo.oneOf.0","typeLabel":"string"},{"type":"null","description":"Up to 200 characters, printed on the letter.","isRequired":true,"uniqueKey":"data.letter.memo.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.memo","typeLabel":"string | null"},"recipient":{"type":"object","required":["name","address"],"properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.name","typeLabel":"string"},"address":{"type":"object","description":"Recipient postal address as stored, with the resolved country name.","required":["line1","line2","landmark","city","region","postal","country","countryName"],"properties":{"line1":{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.address.line1","typeLabel":"string"},"line2":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.address.line2.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.recipient.address.line2.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.recipient.address.line2","typeLabel":"string | null"},"landmark":{"oneOf":[{"type":"string","description":"Printed as `Near …` on the letter.","isRequired":true,"uniqueKey":"data.letter.recipient.address.landmark.oneOf.0","typeLabel":"string"},{"type":"null","description":"Printed as `Near …` on the letter.","isRequired":true,"uniqueKey":"data.letter.recipient.address.landmark.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.recipient.address.landmark","typeLabel":"string | null"},"city":{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.address.city","typeLabel":"string"},"region":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.address.region.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.recipient.address.region.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.recipient.address.region","typeLabel":"string | null"},"postal":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.recipient.address.postal.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.recipient.address.postal.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.recipient.address.postal","typeLabel":"string | null"},"country":{"type":"string","description":"ISO 3166-1 alpha-2, upper-case.","examples":["NG"],"isRequired":true,"uniqueKey":"data.letter.recipient.address.country","typeLabel":"string"},"countryName":{"type":"string","examples":["Nigeria"],"isRequired":true,"uniqueKey":"data.letter.recipient.address.countryName","typeLabel":"string"}},"isRequired":true,"uniqueKey":"data.letter.recipient.address","typeLabel":"object"}},"isRequired":true,"uniqueKey":"data.letter.recipient","typeLabel":"object"},"isDomestic":{"type":"boolean","description":"True when the destination is the deployment's home country (`US` by default).","isRequired":true,"uniqueKey":"data.letter.isDomestic","typeLabel":"boolean"},"expiresAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.letter.expiresAt","typeLabel":"string\u003cdate-time>"},"sender":{"type":"object","required":["walletId","address"],"properties":{"walletId":{"oneOf":[{"type":"string","description":"The sending wallet; `null` if that wallet was later deleted (refunds still go to `address`).","isRequired":true,"uniqueKey":"data.letter.sender.walletId.oneOf.0","typeLabel":"string"},{"type":"null","description":"The sending wallet; `null` if that wallet was later deleted (refunds still go to `address`).","isRequired":true,"uniqueKey":"data.letter.sender.walletId.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.sender.walletId","typeLabel":"string | null"},"address":{"type":"string","description":"EIP-55 address the escrow came from and refunds return to.","isRequired":true,"uniqueKey":"data.letter.sender.address","typeLabel":"string"}},"isRequired":true,"uniqueKey":"data.letter.sender","typeLabel":"object"},"claimCode":{"oneOf":[{"type":"string","description":"Display form (`XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX`, 28 Crockford\nbase32 symbols incl. two check symbols). Owner-only: present on\ncreate and single reads while the letter is non-terminal; `null`\nin lists and once terminal.\n","isRequired":true,"uniqueKey":"data.letter.claimCode.oneOf.0","typeLabel":"string"},{"type":"null","description":"Display form (`XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX`, 28 Crockford\nbase32 symbols incl. two check symbols). Owner-only: present on\ncreate and single reads while the letter is non-terminal; `null`\nin lists and once terminal.\n","isRequired":true,"uniqueKey":"data.letter.claimCode.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claimCode","typeLabel":"string | null"},"claimUrl":{"oneOf":[{"type":"string","description":"`https://\u003caropay-host>/claim#\u003ccode>`; the QR payload. Same visibility as `claimCode`.","isRequired":true,"uniqueKey":"data.letter.claimUrl.oneOf.0","typeLabel":"string"},{"type":"null","description":"`https://\u003caropay-host>/claim#\u003ccode>`; the QR payload. Same visibility as `claimCode`.","isRequired":true,"uniqueKey":"data.letter.claimUrl.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claimUrl","typeLabel":"string | null"},"pdfUrl":{"type":"string","description":"Absolute URL of `GET /transfer/letter/{id}/pdf`, built from the claim origin fixed at creation.","isRequired":true,"uniqueKey":"data.letter.pdfUrl","typeLabel":"string"},"escrow":{"oneOf":[{"type":"object","description":"The `LETTER_ESCROW` leg (sender → vault); `null` only if the row was never created.","required":["transactionId","txHash","explorerUrl","status","verified"],"properties":{"transactionId":{"type":"string","description":"The `Transaction` id; read it with `GET /transactions/{id}`.","examples":["cktxn0005abcd"],"isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.transactionId","typeLabel":"string"},"txHash":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.txHash.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.txHash.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.txHash","typeLabel":"string | null"},"explorerUrl":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.explorerUrl.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.explorerUrl.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.explorerUrl","typeLabel":"string | null"},"status":{"type":"string","enum":["PENDING","CONFIRMED","SETTLING","SETTLED","FAILED"],"description":"The linked transaction's status.","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.status","typeLabel":"enum\u003cstring>"},"verified":{"type":"boolean","description":"True once the leg's `ConfidentialTransfer` event was decrypted and\nmatched the letter amount. The letter only changes status after\nverification, so `CONFIRMED` + `verified: false` means the receipt\nis in and verification is pending.\n","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0.verified","typeLabel":"boolean"}},"isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.0","typeLabel":"object"},{"type":"null","description":"The `LETTER_ESCROW` leg (sender → vault); `null` only if the row was never created.","isRequired":true,"uniqueKey":"data.letter.escrow.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.escrow","typeLabel":"object | null"},"claim":{"oneOf":[{"type":"object","description":"The `LETTER_CLAIM` leg (vault → recipient wallet); `null` until someone claims.","required":["claimedAt","walletAddress","transactionId","txHash","explorerUrl","status","verified"],"properties":{"transactionId":{"type":"string","description":"The `Transaction` id; read it with `GET /transactions/{id}`.","examples":["cktxn0005abcd"],"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.transactionId","typeLabel":"string"},"txHash":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.txHash.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.txHash.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.txHash","typeLabel":"string | null"},"explorerUrl":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.explorerUrl.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.explorerUrl.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.explorerUrl","typeLabel":"string | null"},"status":{"type":"string","enum":["PENDING","CONFIRMED","SETTLING","SETTLED","FAILED"],"description":"The linked transaction's status.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.status","typeLabel":"enum\u003cstring>"},"verified":{"type":"boolean","description":"True once the leg's `ConfidentialTransfer` event was decrypted and\nmatched the letter amount. The letter only changes status after\nverification, so `CONFIRMED` + `verified: false` means the receipt\nis in and verification is pending.\n","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.verified","typeLabel":"boolean"},"claimedAt":{"oneOf":[{"type":"string","format":"date-time","description":"Set when the letter reaches `CLAIMED`.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.claimedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Set when the letter reaches `CLAIMED`.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.claimedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.claimedAt","typeLabel":"string\u003cdate-time> | null"},"walletAddress":{"oneOf":[{"type":"string","description":"The wallet the value was released to.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.walletAddress.oneOf.0","typeLabel":"string"},{"type":"null","description":"The wallet the value was released to.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.walletAddress.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0.walletAddress","typeLabel":"string | null"}},"isRequired":true,"uniqueKey":"data.letter.claim.oneOf.0","typeLabel":"object"},{"type":"null","description":"The `LETTER_CLAIM` leg (vault → recipient wallet); `null` until someone claims.","isRequired":true,"uniqueKey":"data.letter.claim.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.claim","typeLabel":"object | null"},"refund":{"oneOf":[{"type":"object","description":"The `LETTER_REFUND` leg (vault → sender address); `null` unless the letter was voided or expired.","required":["reason","transactionId","txHash","explorerUrl","status","verified"],"properties":{"transactionId":{"type":"string","description":"The `Transaction` id; read it with `GET /transactions/{id}`.","examples":["cktxn0005abcd"],"isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.transactionId","typeLabel":"string"},"txHash":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.txHash.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.txHash.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.txHash","typeLabel":"string | null"},"explorerUrl":{"oneOf":[{"type":"string","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.explorerUrl.oneOf.0","typeLabel":"string"},{"type":"null","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.explorerUrl.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.explorerUrl","typeLabel":"string | null"},"status":{"type":"string","enum":["PENDING","CONFIRMED","SETTLING","SETTLED","FAILED"],"description":"The linked transaction's status.","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.status","typeLabel":"enum\u003cstring>"},"verified":{"type":"boolean","description":"True once the leg's `ConfidentialTransfer` event was decrypted and\nmatched the letter amount. The letter only changes status after\nverification, so `CONFIRMED` + `verified: false` means the receipt\nis in and verification is pending.\n","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.verified","typeLabel":"boolean"},"reason":{"type":"string","enum":["voided","expired"],"isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0.reason","typeLabel":"enum\u003cstring>"}},"isRequired":true,"uniqueKey":"data.letter.refund.oneOf.0","typeLabel":"object"},{"type":"null","description":"The `LETTER_REFUND` leg (vault → sender address); `null` unless the letter was voided or expired.","isRequired":true,"uniqueKey":"data.letter.refund.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.refund","typeLabel":"object | null"},"mail":{"oneOf":[{"type":"object","description":"Fulfilment details; `null` until `POST /transfer/letter/{id}/mail` is attempted.","required":["provider","providerId","deliveryMethod","status","trackingNumber","expectedDeliveryDate","mailedAt","testMode"],"properties":{"provider":{"type":"string","examples":["lob"],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.provider","typeLabel":"string"},"providerId":{"oneOf":[{"type":"string","description":"Lob letter id once accepted.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.providerId.oneOf.0","typeLabel":"string"},{"type":"null","description":"Lob letter id once accepted.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.providerId.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.providerId","typeLabel":"string | null"},"deliveryMethod":{"oneOf":[{"type":"string","enum":["standard","tracked","courier",null],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.deliveryMethod.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["standard","tracked","courier",null],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.deliveryMethod.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.deliveryMethod","typeLabel":"enum\u003cstring> | null"},"status":{"oneOf":[{"type":"string","description":"Lob letter status (`processed`, `rendered`, `failed`), refreshed on owner reads.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.status.oneOf.0","typeLabel":"string"},{"type":"null","description":"Lob letter status (`processed`, `rendered`, `failed`), refreshed on owner reads.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.status.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.status","typeLabel":"string | null"},"trackingNumber":{"oneOf":[{"type":"string","description":"USPS tracking number for `tracked` letters (dummy in test mode).","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.trackingNumber.oneOf.0","typeLabel":"string"},{"type":"null","description":"USPS tracking number for `tracked` letters (dummy in test mode).","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.trackingNumber.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.trackingNumber","typeLabel":"string | null"},"expectedDeliveryDate":{"oneOf":[{"type":"string","description":"Lob's estimate, `YYYY-MM-DD`.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.expectedDeliveryDate.oneOf.0","typeLabel":"string"},{"type":"null","description":"Lob's estimate, `YYYY-MM-DD`.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.expectedDeliveryDate.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.expectedDeliveryDate","typeLabel":"string | null"},"mailedAt":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.mailedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.mailedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.mailedAt","typeLabel":"string\u003cdate-time> | null"},"testMode":{"type":"boolean","description":"True when the deployment uses a Lob test key; nothing is printed or mailed.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0.testMode","typeLabel":"boolean"}},"isRequired":true,"uniqueKey":"data.letter.mail.oneOf.0","typeLabel":"object"},{"type":"null","description":"Fulfilment details; `null` until `POST /transfer/letter/{id}/mail` is attempted.","isRequired":true,"uniqueKey":"data.letter.mail.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.mail","typeLabel":"object | null"},"needsReview":{"type":"boolean","description":"True when a leg could not be verified automatically; nothing moves until an operator reviews `error`.","isRequired":true,"uniqueKey":"data.letter.needsReview","typeLabel":"boolean"},"error":{"oneOf":[{"type":"string","description":"Failure or review context for the most recent leg.","isRequired":true,"uniqueKey":"data.letter.error.oneOf.0","typeLabel":"string"},{"type":"null","description":"Failure or review context for the most recent leg.","isRequired":true,"uniqueKey":"data.letter.error.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.letter.error","typeLabel":"string | null"},"createdAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.letter.createdAt","typeLabel":"string\u003cdate-time>"},"updatedAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.letter.updatedAt","typeLabel":"string\u003cdate-time>"}},"isRequired":true,"uniqueKey":"data.letter","typeLabel":"object"}},"isRequired":true,"uniqueKey":"data","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":true,"data":{"letter":{"id":"cklet0001abcd","status":"ESCROWED","chainId":11155111,"amount":"50.00","token":"cAROUSD","amountVisibility":"sealed","memo":"Thanks for the referral","recipient":{"name":"Jane Doe","address":{"line1":"12 Adeola Odeku Street","line2":"Victoria Island","landmark":"Opposite Eko Hotel","city":"Lagos","region":"LA","postal":null,"country":"NG","countryName":"Nigeria"}},"isDomestic":false,"expiresAt":"2026-10-22T09:45:00.000Z","sender":{"walletId":"ckwlt0001abcd","address":"0x8Ba1f109551bD432803012645Ac136ddd64DBA72"},"claimCode":"7K3M-Q9TX-2ABF-H8RD-5CWN-VGP4-0J6Y","claimUrl":"https://dev.aropay.aro.media/claim#7K3M-Q9TX-2ABF-H8RD-5CWN-VGP4-0J6Y","pdfUrl":"https://dev.aropay.aro.media/api/v1/transfer/letter/cklet0001abcd/pdf","escrow":{"transactionId":"cktxn0005abcd","txHash":"0x4d1e…","explorerUrl":"https://sepolia.etherscan.io/tx/0x4d1e…","status":"CONFIRMED","verified":true},"claim":null,"refund":null,"mail":null,"needsReview":false,"error":null,"createdAt":"2026-09-07T09:45:00.000Z","updatedAt":"2026-09-07T09:45:31.000Z"}}},"examples":{"Example":{"title":"Example","value":{"ok":true,"data":{"letter":{"id":"cklet0001abcd","status":"ESCROWED","chainId":11155111,"amount":"50.00","token":"cAROUSD","amountVisibility":"sealed","memo":"Thanks for the referral","recipient":{"name":"Jane Doe","address":{"line1":"12 Adeola Odeku Street","line2":"Victoria Island","landmark":"Opposite Eko Hotel","city":"Lagos","region":"LA","postal":null,"country":"NG","countryName":"Nigeria"}},"isDomestic":false,"expiresAt":"2026-10-22T09:45:00.000Z","sender":{"walletId":"ckwlt0001abcd","address":"0x8Ba1f109551bD432803012645Ac136ddd64DBA72"},"claimCode":"7K3M-Q9TX-2ABF-H8RD-5CWN-VGP4-0J6Y","claimUrl":"https://dev.aropay.aro.media/claim#7K3M-Q9TX-2ABF-H8RD-5CWN-VGP4-0J6Y","pdfUrl":"https://dev.aropay.aro.media/api/v1/transfer/letter/cklet0001abcd/pdf","escrow":{"transactionId":"cktxn0005abcd","txHash":"0x4d1e…","explorerUrl":"https://sepolia.etherscan.io/tx/0x4d1e…","status":"CONFIRMED","verified":true},"claim":null,"refund":null,"mail":null,"needsReview":false,"error":null,"createdAt":"2026-09-07T09:45:00.000Z","updatedAt":"2026-09-07T09:45:31.000Z"}}}}},"exampleType":"examples"}},"exampleType":"examples"},"b4b1b956-6631-4c31-98b8-afa2fd38fd29":{"description":"Validation failure, invalid or unsupported destination address,\namount above the per-letter cap, external wallet, or insufficient\ncAROUSD (`insufficient_confidential_balance`, also when the escrow\ntransfer clamps to zero).\n","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"invalid_postal_address","message":"US addresses need a two-letter state code and a ZIP or ZIP+4."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"invalid_postal_address","message":"US addresses need a two-letter state code and a ZIP or ZIP+4."}}}},"exampleType":"examples"}},"exampleType":"examples"},"bae16558-a997-40c6-96df-1cb19640066f":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"invalid_api_key","message":"Invalid API key."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"invalid_api_key","message":"Invalid API key."}}}},"exampleType":"examples"}},"exampleType":"examples"},"3b882d8e-287c-413d-a45f-092fa40594de":{"description":"The account has not accepted the current data-privacy terms\n(`terms_not_accepted`, checked before the body is validated;\n`details` carries `version` and `url`), the account is disabled\n(`account_disabled`), or the recipient was blocked by screening\n(`recipient_blocked`, reserved for a future sanctions provider).\n","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"terms_not_accepted":{"title":"terms_not_accepted","value":{"ok":false,"error":{"code":"terms_not_accepted","message":"Accept the AroPay Sandbox data privacy terms before making transactions. Sign in to the dashboard to review and accept them.","details":{"version":"1","url":"/terms"}}}},"account_disabled":{"title":"account_disabled","value":{"ok":false,"error":{"code":"account_disabled","message":"This account is disabled."}}}},"exampleType":"examples"}},"exampleType":"examples"},"ce341672-2297-4692-919d-fd82677d9590":{"description":"Resource not found within this account.","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"not_found","message":"Resource not found."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"not_found","message":"Resource not found."}}}},"exampleType":"examples"}},"exampleType":"examples"},"3564ac7b-e195-42b9-9cc4-1c04250e7ade":{"description":"Rate limit exceeded, or too many letters in flight for this sender\nor destination country (`letter_velocity_limit`).\n","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"letter_velocity_limit","message":"Too many letters in flight. Try again once some are claimed, voided or expired."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"letter_velocity_limit","message":"Too many letters in flight. Try again once some are claimed, voided or expired."}}}},"exampleType":"examples"}},"exampleType":"examples"},"b47281f3-1fe4-4009-9ec9-fa489c9ab647":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"internal_error","message":"An unexpected error occurred."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"internal_error","message":"An unexpected error occurred."}}}},"exampleType":"examples"}},"exampleType":"examples"},"29aaff0d-d0e2-4a9a-b5e3-30fd87ab8baa":{"description":"`transfer_failed`: the escrow transfer reverted on-chain; the\nletter is `FAILED` and nothing left the wallet.\n`escrow_unsettled`: the escrow transfer was broadcast (hash in\n`message`) but bookkeeping failed; the letter stays `DRAFT` with\nthe tx hash on its escrow leg and is reconciled on its next read.\nDo not resubmit; list your letters and poll the draft.\n","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"transfer_failed":{"title":"transfer_failed","value":{"ok":false,"error":{"code":"transfer_failed","message":"Escrow transfer reverted on-chain."}}},"escrow_unsettled":{"title":"escrow_unsettled","value":{"ok":false,"error":{"code":"escrow_unsettled","message":"The escrow transaction 0x5d2c… was submitted but could not be recorded fully; the letter will be reconciled on its next read."}}}},"exampleType":"examples"}},"exampleType":"examples"},"b42729b2-61e8-491a-9218-4a7f08419181":{"description":"No public URL is configured on a production deployment\n(`public_url_not_configured`), or the confidential rail is\nunavailable. Platform-side.\n","content":{"application/json":{"schema":{"type":"object","description":"The shared failure envelope.","required":["ok","error"],"properties":{"ok":{"const":false,"isRequired":true,"uniqueKey":"ok","typeLabel":"any"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code; match on this, not `message`.","isRequired":true,"uniqueKey":"error.code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"details":{"description":"Structured context, e.g. per-field validation issues.","uniqueKey":"error.details","typeLabel":"any"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"ok":false,"error":{"code":"public_url_not_configured","message":"AROPAY_PUBLIC_URL is not configured."}},"examples":{"Example":{"title":"Example","value":{"ok":false,"error":{"code":"public_url_not_configured","message":"AROPAY_PUBLIC_URL is not configured."}}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"06894aaa-108e-4956-bd1d-30d99fa0783d":{"apiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"aro_sk_…","description":"AroPay API key, sent as `Authorization: Bearer aro_sk_…`. Created in\nthe dashboard under Settings → API keys. Takes precedence over a\nsession cookie when both are present.\n","x-default":"aro_sk_your_key_here","scopes":[],"schemeName":"apiKeyAuth"}},"47f3af7a-6853-48a9-8cc8-9b180c45a9ab":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"aropay_session","description":"Browser session cookie minted by `POST /auth/login` (or passkey\nlogin). httpOnly, `SameSite=Lax`, 24 h TTL. Endpoints marked\n**Session-only** accept only this credential and return\n`403 session_required` for API keys.\n","scopes":[],"schemeName":"sessionCookie"}}},"servers":{"c837b5b6-f6c5-4ad6-b620-ca1cf2cae4a7":{"url":"https://aropay.aro.media/api/v1","description":"Production (Ethereum Mainnet)"},"df7e7bea-be31-4d3d-843d-dfab99bc94be":{"url":"https://dev.aropay.aro.media/api/v1","description":"Sandbox (Sepolia)"},"ac04ba04-2f66-410d-9f9f-c4f321306820":{"url":"http://aropay.localhost:3000/api/v1","description":"Local development"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"aro_sk_…","description":"AroPay API key, sent as `Authorization: Bearer aro_sk_…`. Created in\nthe dashboard under Settings → API keys. Takes precedence over a\nsession cookie when both are present.\n","x-default":"aro_sk_your_key_here","scopes":[],"schemeName":"apiKeyAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"AroPay API key, sent as `Authorization: Bearer aro_sk_…`. Created in\nthe dashboard under Settings → API keys. Takes precedence over a\nsession cookie when both are present.\n","format":"bearer","default":"aro_sk_your_key_here","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"apiKeyAuth","name":"Authorization"}],"title":"apiKeyAuth"},{"schemes":[{"scheme":{"type":"apiKey","in":"cookie","name":"aropay_session","description":"Browser session cookie minted by `POST /auth/login` (or passkey\nlogin). httpOnly, `SameSite=Lax`, 24 h TTL. Endpoints marked\n**Session-only** accept only this credential and return\n`403 session_required` for API keys.\n","scopes":[],"schemeName":"sessionCookie"},"schema":{"title":"aropay_session","type":"string","description":"Browser session cookie minted by `POST /auth/login` (or passkey\nlogin). httpOnly, `SameSite=Lax`, 24 h TTL. Endpoints marked\n**Session-only** accept only this credential and return\n`403 session_required` for API keys.\n","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"sessionCookie","name":"aropay_session"}],"title":"sessionCookie"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"aro-pay","siteName":"AroPay","title":"Create letter - AroPay","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-28T23:17:50.024Z","originalFileLocation":"api-reference/aro-mail/create-letter.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Turn a private cAROUSD transfer into a mailable letter. Escrows amount from a custodial wallet into the Aro Mail vault (a confidentialTransfer to the platform operator) and returns the letter with its one-time claimCode, the claimUrl the QR encodes (https:///claim#, code in the URL fragment), and the pdfUrl of the printable page. Defaults depend on the destination: domestic letters (destination = the deployment\u0026#x27;s home country, US by default) are visible and expire in 90 days; international letters are sealed and expire in 45 days. Addresses follow the destination\u0026#x27;s rules (US: two-letter state, ZIP or ZIP+4, 64-character lines; elsewhere region or postal is required). Amounts above the per-letter cap return 400 invalid_amount; too many letters in flight return 429 letter_velocity_limit. Blocks up to ~20 s for the escrow receipt. A letter returned as DRAFT with a PENDING escrow leg becomes ESCROWED on a later read once the receipt lands and the encrypted amount is verified; a reverted or clamped escrow becomes FAILED with nothing moved. If the escrow was broadcast but the bookkeeping after it failed, the call returns 502 escrow_unsettled instead of the letter: the letter exists as DRAFT (find it in GET /transfer/letter), value has left the wallet, and reconciliation finishes it on the next read. Do not create it again. claimCode and claimUrl are returned only here and on GET /transfer/letter/{id}, only to the owner, and only while the letter is not terminal. Anyone holding the code can claim once.\">\u003cmeta data-mint-head name=\"application-name\" content=\"AroPay\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Create letter - AroPay\">\u003cmeta data-mint-head property=\"og:description\" content=\"Turn a private cAROUSD transfer into a mailable letter. Escrows amount from a custodial wallet into the Aro Mail vault (a confidentialTransfer to the platform operator) and returns the letter with its one-time claimCode, the claimUrl the QR encodes (https:///claim#, code in the URL fragment), and the pdfUrl of the printable page. Defaults depend on the destination: domestic letters (destination = the deployment\u0026#x27;s home country, US by default) are visible and expire in 90 days; international letters are sealed and expire in 45 days. Addresses follow the destination\u0026#x27;s rules (US: two-letter state, ZIP or ZIP+4, 64-character lines; elsewhere region or postal is required). Amounts above the per-letter cap return 400 invalid_amount; too many letters in flight return 429 letter_velocity_limit. Blocks up to ~20 s for the escrow receipt. A letter returned as DRAFT with a PENDING escrow leg becomes ESCROWED on a later read once the receipt lands and the encrypted amount is verified; a reverted or clamped escrow becomes FAILED with nothing moved. If the escrow was broadcast but the bookkeeping after it failed, the call returns 502 escrow_unsettled instead of the letter: the letter exists as DRAFT (find it in GET /transfer/letter), value has left the wallet, and reconciliation finishes it on the next read. Do not create it again. claimCode and claimUrl are returned only here and on GET /transfer/letter/{id}, only to the owner, and only while the letter is not terminal. Anyone holding the code can claim once.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"AroPay Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://aro-pay.mintlify.app/_mintlify/api/og/v2?division=Aro+Mail\u0026amp;title=Create+letter\u0026amp;description=Turn+a+private+cAROUSD+transfer+into+a+mailable+letter.+Escrows%0A%60amount%60+from+a+**custodial**+wallet+into+the+Aro+Mail+vault+%28a%0A%60confidentialTransfer%60+to+the+pl\u0026amp;theme=3704c013118512784ba7c5bd\u0026amp;signature=143502fb92815f8012c796cee9eee0f972705ee848b98190e85068b15fcf9313\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Create letter - AroPay\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Turn a private cAROUSD transfer into a mailable letter. Escrows amount from a custodial wallet into the Aro Mail vault (a confidentialTransfer to the platform operator) and returns the letter with its one-time claimCode, the claimUrl the QR encodes (https:///claim#, code in the URL fragment), and the pdfUrl of the printable page. Defaults depend on the destination: domestic letters (destination = the deployment\u0026#x27;s home country, US by default) are visible and expire in 90 days; international letters are sealed and expire in 45 days. Addresses follow the destination\u0026#x27;s rules (US: two-letter state, ZIP or ZIP+4, 64-character lines; elsewhere region or postal is required). Amounts above the per-letter cap return 400 invalid_amount; too many letters in flight return 429 letter_velocity_limit. Blocks up to ~20 s for the escrow receipt. A letter returned as DRAFT with a PENDING escrow leg becomes ESCROWED on a later read once the receipt lands and the encrypted amount is verified; a reverted or clamped escrow becomes FAILED with nothing moved. If the escrow was broadcast but the bookkeeping after it failed, the call returns 502 escrow_unsettled instead of the letter: the letter exists as DRAFT (find it in GET /transfer/letter), value has left the wallet, and reconciliation finishes it on the next read. Do not create it again. claimCode and claimUrl are returned only here and on GET /transfer/letter/{id}, only to the owner, and only while the letter is not terminal. Anyone holding the code can claim once.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://aro-pay.mintlify.app/_mintlify/api/og/v2?division=Aro+Mail\u0026amp;title=Create+letter\u0026amp;description=Turn+a+private+cAROUSD+transfer+into+a+mailable+letter.+Escrows%0A%60amount%60+from+a+**custodial**+wallet+into+the+Aro+Mail+vault+%28a%0A%60confidentialTransfer%60+to+the+pl\u0026amp;theme=3704c013118512784ba7c5bd\u0026amp;signature=143502fb92815f8012c796cee9eee0f972705ee848b98190e85068b15fcf9313\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/aro-pay/oJpOT1vgvGU8ulqs/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"AroPay\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#8A7C63\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/aro-mail/create-letter.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.aropay.aro.media/#organization\",\"name\":\"AroPay\",\"url\":\"https://docs.aropay.aro.media\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/aro-pay/KNYEWxjVGo5XgIrA/logo/light.svg?fit=max\u0026auto=format\u0026n=KNYEWxjVGo5XgIrA\u0026q=85\u0026s=bb49753238a5be47e146c889187987bc\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.aropay.aro.media#website\",\"name\":\"AroPay\",\"url\":\"https://docs.aropay.aro.media\",\"publisher\":{\"@id\":\"https://docs.aropay.aro.media/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter#webpage\",\"url\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter\",\"name\":\"Create letter\",\"description\":\"Turn a private cAROUSD transfer into a mailable letter. Escrows amount from a custodial wallet into the Aro Mail vault (a confidentialTransfer to the platform operator) and returns the letter with its one-time claimCode, the claimUrl the QR encodes (https:///claim#, code in the URL fragment), and the pdfUrl of the printable page. Defaults depend on the destination: domestic letters (destination = the deployment's home country, US by default) are visible and expire in 90 days; international letters are sealed and expire in 45 days. Addresses follow the destination's rules (US: two-letter state, ZIP or ZIP+4, 64-character lines; elsewhere region or postal is required). Amounts above the per-letter cap return 400 invalid_amount; too many letters in flight return 429 letter_velocity_limit. Blocks up to ~20 s for the escrow receipt. A letter returned as DRAFT with a PENDING escrow leg becomes ESCROWED on a later read once the receipt lands and the encrypted amount is verified; a reverted or clamped escrow becomes FAILED with nothing moved. If the escrow was broadcast but the bookkeeping after it failed, the call returns 502 escrow_unsettled instead of the letter: the letter exists as DRAFT (find it in GET /transfer/letter), value has left the wallet, and reconciliation finishes it on the next read. Do not create it again. claimCode and claimUrl are returned only here and on GET /transfer/letter/{id}, only to the owner, and only while the letter is not terminal. Anyone holding the code can claim once.\",\"dateModified\":\"2026-10-28T23:17:50.024Z\",\"isPartOf\":{\"@id\":\"https://docs.aropay.aro.media#website\"},\"breadcrumb\":{\"@id\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"AroPay\",\"item\":\"https://docs.aropay.aro.media\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create letter\",\"item\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter#apireference\",\"headline\":\"Create letter\",\"name\":\"Create letter\",\"description\":\"Turn a private cAROUSD transfer into a mailable letter. Escrows amount from a custodial wallet into the Aro Mail vault (a confidentialTransfer to the platform operator) and returns the letter with its one-time claimCode, the claimUrl the QR encodes (https:///claim#, code in the URL fragment), and the pdfUrl of the printable page. Defaults depend on the destination: domestic letters (destination = the deployment's home country, US by default) are visible and expire in 90 days; international letters are sealed and expire in 45 days. Addresses follow the destination's rules (US: two-letter state, ZIP or ZIP+4, 64-character lines; elsewhere region or postal is required). Amounts above the per-letter cap return 400 invalid_amount; too many letters in flight return 429 letter_velocity_limit. Blocks up to ~20 s for the escrow receipt. A letter returned as DRAFT with a PENDING escrow leg becomes ESCROWED on a later read once the receipt lands and the encrypted amount is verified; a reverted or clamped escrow becomes FAILED with nothing moved. If the escrow was broadcast but the bookkeeping after it failed, the call returns 502 escrow_unsettled instead of the letter: the letter exists as DRAFT (find it in GET /transfer/letter), value has left the wallet, and reconciliation finishes it on the next read. Do not create it again. claimCode and claimUrl are returned only here and on GET /transfer/letter/{id}, only to the owner, and only while the letter is not terminal. Anyone holding the code can claim once.\",\"url\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter\",\"mainEntityOfPage\":{\"@id\":\"https://docs.aropay.aro.media/api-reference/aro-mail/create-letter#webpage\"},\"dateModified\":\"2026-10-28T23:17:50.024Z\",\"publisher\":{\"@id\":\"https://docs.aropay.aro.media/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.aropay.aro.media#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"AroPay\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"AroPay","nav":{"global":null,"tabs":[{"tab":"Documentation","icon":{"style":"duotone","name":"book-open"},"pages":[{"title":"Documentation","href":""}]},{"tab":"API reference","icon":{"style":"duotone","name":"code"},"groups":[{"group":"Using the API","icon":{"style":"duotone","name":"compass"},"pages":[{"title":"API introduction","sidebarTitle":"Introduction","icon":"compass","iconType":"duotone","href":"/api-reference/introduction"},{"title":"Errors","icon":"triangle-exclamation","iconType":"duotone","href":"/api-reference/errors"}]},{"group":"Auth","icon":{"style":"duotone","name":"right-to-bracket"},"pages":[{"title":"Log in","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /auth/login","href":"/api-reference/auth/log-in"},{"title":"Complete TOTP login","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /auth/login/totp","href":"/api-reference/auth/complete-totp-login"},{"title":"Get passkey login options","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /auth/passkey/options","href":"/api-reference/auth/get-passkey-login-options"},{"title":"Verify passkey login","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /auth/passkey/verify","href":"/api-reference/auth/verify-passkey-login"},{"title":"Get session","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /auth/session","href":"/api-reference/auth/get-session"},{"title":"Log out","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /auth/logout","href":"/api-reference/auth/log-out"}]},{"group":"Profile \u0026 security","icon":{"style":"duotone","name":"user-shield"},"pages":[{"title":"Get profile","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /me","href":"/api-reference/profile-\u0026-security/get-profile"},{"title":"Update profile","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /me","href":"/api-reference/profile-\u0026-security/update-profile"},{"title":"Change password","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/password","href":"/api-reference/profile-\u0026-security/change-password"},{"title":"Get privacy terms","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /me/terms","href":"/api-reference/profile-\u0026-security/get-privacy-terms"},{"title":"Accept privacy terms","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/terms","href":"/api-reference/profile-\u0026-security/accept-privacy-terms"},{"title":"Set up TOTP","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/totp/setup","href":"/api-reference/profile-\u0026-security/set-up-totp"},{"title":"Enable TOTP","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/totp/enable","href":"/api-reference/profile-\u0026-security/enable-totp"},{"title":"Disable TOTP","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/totp/disable","href":"/api-reference/profile-\u0026-security/disable-totp"},{"title":"List passkeys","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /me/passkeys","href":"/api-reference/profile-\u0026-security/list-passkeys"},{"title":"Get passkey registration options","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/passkeys/options","href":"/api-reference/profile-\u0026-security/get-passkey-registration-options"},{"title":"Register passkey","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /me/passkeys/register","href":"/api-reference/profile-\u0026-security/register-passkey"},{"title":"Delete passkey","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /me/passkeys/{id}","href":"/api-reference/profile-\u0026-security/delete-passkey"}]},{"group":"API keys","icon":{"style":"duotone","name":"key"},"pages":[{"title":"List API keys","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /keys","href":"/api-reference/api-keys/list-api-keys"},{"title":"Create API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /keys","href":"/api-reference/api-keys/create-api-key"},{"title":"Revoke API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /keys/{id}","href":"/api-reference/api-keys/revoke-api-key"}]},{"group":"Wallets","icon":{"style":"duotone","name":"wallet"},"pages":[{"title":"List wallets","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /wallets","href":"/api-reference/wallets/list-wallets"},{"title":"Create wallet","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /wallets","href":"/api-reference/wallets/create-wallet"},{"title":"Get wallet","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /wallets/{id}","href":"/api-reference/wallets/get-wallet"},{"title":"Get address card","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /wallets/{id}/nota","href":"/api-reference/wallets/get-address-card"},{"title":"Export wallet key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /wallets/{id}/export","href":"/api-reference/wallets/export-wallet-key"}]},{"group":"Balances","icon":{"style":"duotone","name":"coins"},"pages":[{"title":"Get balances","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /balances","href":"/api-reference/balances/get-balances"},{"title":"Get gas balances","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /gas","href":"/api-reference/balances/get-gas-balances"}]},{"group":"Money movement","icon":{"style":"duotone","name":"money-bill-transfer"},"pages":[{"title":"Fund wallet","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /fund","href":"/api-reference/money-movement/fund-wallet"},{"title":"Mint cAROUSD","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /mint","href":"/api-reference/money-movement/mint-carousd"},{"title":"Transfer funds","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer","href":"/api-reference/money-movement/transfer-funds"},{"title":"Redeem cAROUSD","description":"Burn cAROUSD from a **custodial** wallet and receive public test\nstablecoin 1:1. Two legs, both driven by the background worker: the\ntransaction moves `QUEUED → PENDING` (burn submitted) `→ SETTLING`\n(burn confirmed) `→ SETTLED` (operator payout confirmed), with the\npayout hash in `settlementTxHash` and the amount actually paid out in\n`payout` (`payout.partial` is `true` when nothing, or less than\nrequested, was paid).\n\nAsynchronous: returns `201` immediately with the transaction in status\n`QUEUED` (`txHash: null`). Poll `GET /transactions/{id}` until\n`status` is `SETTLED` or `FAILED`. Execution failures surface as\nstatus `FAILED` with `errorCode` on the transaction (e.g.\n`redeem_failed`, `insufficient_confidential_balance`), not as an HTTP\nerror; `FAILED` is only reachable before the burn confirmed, so a\nfailed redeem never burned anything.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /redeem","href":"/api-reference/money-movement/redeem-carousd"}]},{"group":"Aro Mail","icon":{"style":"duotone","name":"envelope"},"pages":[{"title":"Create letter","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter","href":"/api-reference/aro-mail/create-letter"},{"title":"List letters","description":"Your letters, newest first. In-flight rows are reconciled on read\n(receipt lookups, amount verification, expiry detection) but this\nendpoint never moves money or calls Lob. Items omit `claimCode` and\n`claimUrl`; read a single letter for those.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transfer/letter","href":"/api-reference/aro-mail/list-letters"},{"title":"Get letter","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transfer/letter/{id}","href":"/api-reference/aro-mail/get-letter"},{"title":"Download letter PDF","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transfer/letter/{id}/pdf","href":"/api-reference/aro-mail/download-letter-pdf"},{"title":"Mail letter","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter/{id}/mail","href":"/api-reference/aro-mail/mail-letter"},{"title":"Void letter","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter/{id}/void","href":"/api-reference/aro-mail/void-letter"},{"title":"Preview claim","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter/claim/preview","href":"/api-reference/aro-mail/preview-claim"},{"title":"Claim letter","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter/claim","href":"/api-reference/aro-mail/claim-letter"},{"title":"Sweep expired letters","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /transfer/letter/sweep","href":"/api-reference/aro-mail/sweep-expired-letters"}]},{"group":"Transactions","icon":{"style":"duotone","name":"receipt"},"pages":[{"title":"List transactions","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transactions","href":"/api-reference/transactions/list-transactions"},{"title":"Get transaction","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transactions/{id}","href":"/api-reference/transactions/get-transaction"},{"title":"Get transaction receipt","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /transactions/{id}/nota","href":"/api-reference/transactions/get-transaction-receipt"}]},{"group":"Sandbox","icon":{"style":"duotone","name":"flask-vial"},"pages":[{"title":"Get sandbox status","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /sandbox","href":"/api-reference/sandbox/get-sandbox-status"},{"title":"Echo JSON","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /sandbox","href":"/api-reference/sandbox/echo-json"}]}]}]},"basePath":"","title":"Create letter - AroPay","buildId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","deploymentId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CS552b7R.js","utils-DDTCYAF2.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-De8ttokP.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-DrwRDvAh.js","snippetPresets-DtAN0nWx.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-D5rWArI6.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-O2i12wsz.js","shallow-DV8xABTt.js","getApiPlaygroundDisplay-DBZ0B5Jx.js","CodeSnippet-BVi0tPUX.js","CodeSnippets-CqASbIwY.js","Page-m07pfKpT.js","getPastedJson-DG9vsMS8.js","icon-CXzRSCr8.js","MethodPill-BdKVtEuX.js","DuplicateIcon-CZlmBrJI.js","createIcon-biFEUKPL.js","DynamicMarkdown-B54_zNBF.js","SectionHeading-DwwHK3Pt.js","axios-vUo_bRtp.js","Markdown-DfhCTwyA.js","clsx-xpJZXxdP.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-BTZUMDnx.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-DqdKa2R4.js"]}