> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aropay.aro.media/llms.txt
> Use this file to discover all available pages before exploring further.

# nota-mail (proposal)

> Proposal: turn a confidential cAROUSD transfer into a mailable letter that the recipient claims on the platform via QR, or link.

<Note>
  This page is an internal proposal for the engineering team. Nothing here ships until scoped and approved. Endpoints and screens shown below are illustrative.
</Note>

## The idea in one paragraph

**nota-mail** turns a private cAROUSD transfer into a physical letter. The sender prints (or has AroPay print and mail) a letter carrying a QR code and short claim code. The recipient scans the QR, lands on a claim page, signs in or creates a wallet, and the escrowed cAROUSD moves into their wallet. From there they can hold cAROUSD, transfer it privately, or [redeem](/guides/redeem-carousd) it for USDC or USDT. AroPay delivers the digital dollars; local fiat conversion is the recipient's responsibility.

## Why it fits AroPay

* Extends [confidential transfers](/concepts/confidential-transfers) into an offline delivery channel while preserving the same encrypted-amount guarantees.
* Reuses [.nota files](/concepts/nota-files) as the identity artifact and visual language.
* Reaches recipients without existing wallets or reliable internet at send time.
* Enterprise use cases: remittances, gifts, disaster relief, legal payments, unbanked payouts.

## Scope boundary

<Columns cols={2}>
  <Card title="AroPay owns" icon="circle-check" iconType="duotone">
    Escrow, print, mail, claim, delivery of cAROUSD to the recipient's wallet, and redeem to USDC/USDT.
  </Card>

  <Card title="AroPay does not own" icon="circle-xmark" iconType="duotone">
    Local fiat conversion (NGN, INR, PHP, etc.), bank payouts, or off-ramp partnerships. The recipient handles cash-out.
  </Card>
</Columns>

## nota-mail as a 7-layer stack

The OSI model is a useful frame here because nota-mail is a protocol: it takes value at one end, encodes it through several independent layers (crypto, escrow, print, postage, scan, claim), and reconstructs it at the other end. Each layer has one job and a clean handoff to the next. If a layer fails (letter lost, QR damaged, wallet not set up), only that layer needs recovery, not the whole system.

```mermaid theme={"system"}
flowchart TB
  L7["L7 Application \u00b7 Sender & recipient intent (send $50, claim $50)"]
  L6["L6 Presentation \u00b7 Letter rendering (PDF, QR, claim code, sealed amount)"]
  L5["L5 Session \u00b7 Claim session (one-time code, single-use, expiry sweep)"]
  L4["L4 Transport \u00b7 Escrow contract (reliable delivery of encrypted cAROUSD)"]
  L3["L3 Network \u00b7 Postal routing (address, region, country, courier fallback)"]
  L2["L2 Data link \u00b7 Envelope + stamp (Lob / PostGrid / Global Forever)"]
  L1["L1 Physical \u00b7 Paper letter moving through the mail system"]
  L7 --> L6 --> L5 --> L4 --> L3 --> L2 --> L1
```

<AccordionGroup>
  <Accordion title="L1 \u00b7 Physical: the paper letter" icon="envelope-open">
    The actual sheet of paper carrying ink. AroPay owns the layout template; the postal carrier owns the transit.

    **Responsibilities:** paper stock, print quality, QR contrast, tamper-evident fold. **Failure mode:** letter lost, damaged, or destroyed in transit. **Recovery:** expiry sweep at L5, then void at L4.
  </Accordion>

  <Accordion title="L2 \u00b7 Data link: envelope, stamp, provider handoff" icon="stamp">
    The framing layer that gets a letter from AroPay onto the postal network. `POST /transfer/letter/{id}/mail` selects a provider (Lob, PostGrid, Letter Labs) and a `deliveryMethod` (`standard`, `tracked`, `courier`). Postage is Forever stamps domestic, Global Forever international.

    **Responsibilities:** provider API, postage math, tracking IDs, courier fallback. **Failure mode:** `402 postage_unavailable`, provider outage. **Recovery:** retry with alternate provider; escalate to `courier` for high-value letters.
  </Accordion>

  <Accordion title="L3 \u00b7 Network: addressing and routing" icon="signs-post">
    Global address resolution. Flexible schema so recipient addresses in Nigeria, India, or the Philippines route as cleanly as US ones. Uses ISO 3166 country and 3166-2 region codes; `postal` optional; `landmark` supported.

    **Responsibilities:** address validation, country-aware rules, sanctions/PEP screening on names and addresses. **Failure mode:** `400 invalid_postal_address`, sanctions hit. **Recovery:** sender fixes address at L7 and reissues; sanctions hits are hard-fail.
  </Accordion>

  <Accordion title="L4 \u00b7 Transport: escrow of encrypted value" icon="lock">
    The reliable-delivery layer. `POST /transfer/letter` moves cAROUSD from the sender's custodial wallet into an escrow state, encrypted under FHE. Value cannot be lost or duplicated regardless of what happens at L1\u2013L3.

    **Responsibilities:** debit sender, hold ciphertext, honor void, honor expiry sweep. **Failure mode:** `400 validation_error` (insufficient balance), `502 transfer_failed`. **Recovery:** transaction row carries the error; sender retries.
  </Accordion>

  <Accordion title="L5 \u00b7 Session: claim lifecycle" icon="ticket">
    The one-time session that binds a physical letter to a single successful claim. 128-bit claim secret, base32 encoded with checksum, embedded in the QR and printed as `6H2K-QT4P`. Status machine: `ESCROWED \u2192 MAILED \u2192 CLAIMED | EXPIRED | VOIDED`.

    **Responsibilities:** atomic status flip, single-use enforcement, expiry timers, void authorization. **Failure mode:** `409 already_claimed`, `410 letter_expired`. **Recovery:** expired letters auto-refund the sender; already-claimed letters are terminal.
  </Accordion>

  <Accordion title="L6 \u00b7 Presentation: how the letter looks" icon="file-pdf">
    Rendering of the escrowed transfer into something a human can read and a phone camera can decode. PDF layout, QR encoding, sealed vs. visible amount, sender/recipient blocks, expiry, and .nota-style branding.

    **Responsibilities:** PDF generation, QR contrast, `amountVisibility: sealed | visible`, localization of labels. **Failure mode:** `400 amount_visibility_invalid`, unreadable QR. **Recovery:** regenerate PDF from the same letter id at L5; the escrowed value at L4 does not change.
  </Accordion>

  <Accordion title="L7 \u00b7 Application: sender and recipient intent" icon="user">
    What a human is actually trying to do. Sender: "pay Jane \$50 privately, she has no wallet yet." Recipient: "claim the letter I received."

    **Responsibilities:** sender UX for creating the letter, recipient UX at `claim.aropay.aro.media/{code}`, optional [redeem](/guides/redeem-carousd) to USDC/USDT after claim. **Failure mode:** recipient scans but abandons wallet setup. **Recovery:** hold claim reservation for N minutes (open question), then release the code for retry.
  </Accordion>
</AccordionGroup>

### Layer boundary at claim

When the recipient scans, the layers unwind in reverse: L1 delivers paper, L6 decodes the QR, L5 validates the session, L4 releases escrow into the recipient's wallet. L7 then decides what to do next: hold, transfer, or redeem.

## End-to-end flow

```mermaid theme={"system"}
flowchart TD
  A["Sender<br/>custodial wallet"] -->|"POST /transfer/letter<br/>amount + recipient"| B["Escrow<br/>encrypted cAROUSD"]
  B --> C["Letter artifact<br/>PDF + QR + claim code"]
  C -->|"self-print + stamp"| D["Postal system"]
  C -->|"POST /transfer/letter/:id/mail<br/>Lob / PostGrid"| D
  D --> E["Recipient<br/>opens envelope"]
  E -->|"scan QR or open link"| F["claim.aropay..."]
  F -->|"POST /transfer/letter/claim"| G["Recipient wallet<br/>cAROUSD credited"]
  G -->|"optional POST /redeem"| H["USDC / USDT<br/>in recipient wallet"]
  B -. "expiry sweep" .-> A
```

### Status machine

`DRAFT` → `ESCROWED` → `MAILED` (optional) → `CLAIMED` | `EXPIRED` | `VOIDED`

## What the letter looks like

Rendered mockup of a sandbox letter. Real letters use the recipient's postal address and a signed QR payload.

<Frame>
  <div
    style={{
fontFamily: "ui-sans-serif, system-ui, sans-serif",
background: "#faf7f2",
color: "#1a1a1a",
border: "1px solid #d9d3c7",
borderRadius: "8px",
padding: "32px",
maxWidth: "640px",
margin: "0 auto",
boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
}}
  >
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", borderBottom: "1px solid #d9d3c7", paddingBottom: "16px", marginBottom: "20px" }}>
      <div>
        <div style={{ fontSize: "11px", letterSpacing: "0.15em", color: "#8a7f6c", textTransform: "uppercase" }}>AroPay · nota-mail</div>
        <div style={{ fontSize: "20px", fontWeight: 600, marginTop: "4px" }}>Confidential Letter of Value</div>
      </div>

      <div style={{ textAlign: "right", fontSize: "11px", color: "#8a7f6c" }}>
        <div>LETTER ID</div>
        <div style={{ color: "#1a1a1a", fontFamily: "ui-monospace, monospace" }}>cklet0001a2b3</div>
      </div>
    </div>

    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "20px", marginBottom: "24px" }}>
      <div>
        <div style={{ fontSize: "10px", letterSpacing: "0.12em", color: "#8a7f6c", textTransform: "uppercase", marginBottom: "4px" }}>From</div>

        <div style={{ fontSize: "13px", lineHeight: 1.4 }}>
          Acme Payroll, Inc.<br />
          Wallet 0x8Ba1...BA72
        </div>
      </div>

      <div>
        <div style={{ fontSize: "10px", letterSpacing: "0.12em", color: "#8a7f6c", textTransform: "uppercase", marginBottom: "4px" }}>To</div>

        <div style={{ fontSize: "13px", lineHeight: 1.4 }}>
          Jane Doe<br />
          12 Adeola Odeku Street<br />
          Victoria Island, Lagos LA<br />
          Nigeria
        </div>
      </div>
    </div>

    <div style={{ background: "#fff", border: "1px dashed #c9c0ac", borderRadius: "6px", padding: "20px", textAlign: "center", marginBottom: "24px" }}>
      <div style={{ fontSize: "10px", letterSpacing: "0.12em", color: "#8a7f6c", textTransform: "uppercase", marginBottom: "8px" }}>Sealed amount</div>
      <div style={{ fontSize: "28px", fontWeight: 700, letterSpacing: "0.02em" }}>••••••• cAROUSD</div>
      <div style={{ fontSize: "11px", color: "#8a7f6c", marginTop: "6px" }}>Revealed to recipient on claim</div>
    </div>

    <div style={{ display: "grid", gridTemplateColumns: "120px 1fr", gap: "20px", alignItems: "center", marginBottom: "20px" }}>
      <div
        style={{
width: "120px",
height: "120px",
background: "repeating-conic-gradient(#1a1a1a 0% 25%, #faf7f2 0% 50%) 50% / 12px 12px",
border: "6px solid #faf7f2",
boxShadow: "0 0 0 1px #1a1a1a",
borderRadius: "4px"
}}
      />

      <div>
        <div style={{ fontSize: "10px", letterSpacing: "0.12em", color: "#8a7f6c", textTransform: "uppercase", marginBottom: "4px" }}>Claim at</div>
        <div style={{ fontSize: "14px", fontFamily: "ui-monospace, monospace" }}>claim.aropay.aro.media/6H2K-QT4P</div>
        <div style={{ fontSize: "10px", letterSpacing: "0.12em", color: "#8a7f6c", textTransform: "uppercase", margin: "10px 0 4px" }}>Or enter code</div>
        <div style={{ fontSize: "18px", fontWeight: 600, fontFamily: "ui-monospace, monospace", letterSpacing: "0.1em" }}>6H2K-QT4P</div>
      </div>
    </div>

    <div style={{ fontSize: "11px", color: "#8a7f6c", borderTop: "1px solid #d9d3c7", paddingTop: "12px", display: "flex", justifyContent: "space-between" }}>
      <span>Expires 2026-11-13</span>
      <span>One-time claim · Do not photograph</span>
    </div>
  </div>
</Frame>

## Illustrative API

Final shape lives in the OpenAPI spec once scoped. This is the shape the flow assumes.

### Create a letter

```http theme={"system"}
POST /transfer/letter
```

```json theme={"system"}
{
  "walletId": "ckwlt0001...",
  "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,
  "format": "pdf"
}
```

```json theme={"system"}
{
  "ok": true,
  "data": {
    "letter": {
      "id": "cklet0001a2b3",
      "status": "ESCROWED",
      "claimUrl": "https://claim.aropay.aro.media/6H2K-QT4P",
      "claimCode": "6H2K-QT4P",
      "pdfUrl": "https://.../letters/cklet0001a2b3/letter.pdf",
      "expiresAt": "2026-09-29T00:00:00.000Z",
      "amount": { "encrypted": true, "handle": "0x8f2c..." }
    }
  }
}
```

### Print and mail on the sender's behalf

```http theme={"system"}
POST /transfer/letter/{id}/mail
```

```json theme={"system"}
{ "deliveryMethod": "tracked", "provider": "lob" }
```

### Claim

```http theme={"system"}
POST /transfer/letter/claim
```

```json theme={"system"}
{ "claimCode": "6H2K-QT4P", "walletId": "ckwlt0004..." }
```

Moves cAROUSD from escrow into the claiming wallet. Idempotent, single-use.

### Void

```http theme={"system"}
POST /transfer/letter/{id}/void
```

Returns funds to the sender while `status === "ESCROWED"`.

## Design constraints for the team

* **Claim secret.** 128-bit random, base32 with checksum, embedded in QR and printed code.
* **Single-use claim.** Atomic status flip; second scan returns `409 already_claimed`.
* **Sealed vs visible amount.** `sealed` (default for international) hides amount on the printed letter; `visible` prints it.
* **Expiry sweep.** Background job refunds sender after `expiresAt`. Default 90 days domestic, 45 days international.
* **Address flexibility.** Do not require `postal`. Accept `landmark`. Use ISO 3166-2 regions.
* **Fulfillment abstraction.** Thin provider interface: Lob, PostGrid, Letter Labs. Postage via Global Forever for international.
* **Sanctions/PEP screening.** Runs on `POST /transfer/letter` before escrow, on recipient name and address.
* **Velocity limits.** Per-country cap on unclaimed letters in flight.
* **New failure modes.** `400 invalid_postal_address`, `400 amount_visibility_invalid`, `402 postage_unavailable`, `404 letter_not_found`, `409 already_claimed`, `410 letter_expired`.

## Open questions

1. Escrow: new contract or a locked-balance pattern on cAROUSD?
2. Fulfillment provider of record for MVP: Lob, PostGrid, or Letter Labs?
3. Print amount on the envelope for postal insurance, or fully sealed until claim?
4. Recovery flow if the recipient scans but never completes wallet setup: how long do we hold the reservation?
5. Country rollout: US-only pilot, or open international from day one with a per-country flag?

## Docs impact when it ships

* New guide **Send a nota-mail letter** under [Guides](/guides/send-transfers), sibling to Send transfers.
* Update the mint/redeem diagram on [Confidential transfers](/concepts/confidential-transfers) to include the escrow → mail → claim path.
* Add letter endpoints to the API reference.
* Add an Availability matrix (supported countries, delivery methods, transit times).
