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

# Cash-in

> How to let a customer deposit physical cash at a retail location and receive USDC in their wallet.

<Note>
  **Before you start:** the OMS API is in early access. Every endpoint, including the ones in this guide, requires an early-access API key. [Request access](https://info.polygon.technology/get-early-access?utm_source=docs\&utm_medium=card\&utm_campaign=oms_access) before you begin.
</Note>

<div style={{border:"1px solid #C8CFE1",borderRadius:"12px",overflow:"hidden",marginBottom:"24px"}}>
  <div style={{background:"linear-gradient(180deg,#EAE4F5 0%,#F6F3FB 100%)",borderBottom:"1px solid #D5C4F2",padding:"10px 16px",fontSize:"11px",fontWeight:"700",color:"#670DE5",letterSpacing:"0.06em",textTransform:"uppercase"}}>Cash-in flow</div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>1</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>App</span>
    <span style={{color:"#670DE5",fontWeight:"700"}}>→</span>
    <span style={{background:"#EAE4F5",color:"#670DE5",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"700",whiteSpace:"nowrap"}}>OMS</span>
    <span style={{fontFamily:"'Geist Mono',ui-monospace,monospace",fontSize:"12px",color:"#141635"}}>POST /cash-ins (destination, location, indicatedAmount)</span>
  </div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>2</span>
    <span style={{background:"#EAE4F5",color:"#670DE5",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"700",whiteSpace:"nowrap"}}>OMS</span>
    <span style={{color:"#48526F",fontWeight:"700"}}>→</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>App</span>
    <span style={{fontFamily:"'Geist Mono',ui-monospace,monospace",fontSize:"12px",color:"#141635"}}>\{depositCode: "XXXX-XXXX", expiresAt}</span>
  </div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>3</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>App</span>
    <span style={{color:"#670DE5",fontWeight:"700"}}>→</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>Customer</span>
    <span style={{fontSize:"13px",color:"#141635"}}>Show deposit code + nearby location</span>
  </div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>4</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>Customer</span>
    <span style={{color:"#670DE5",fontWeight:"700"}}>→</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>Retail</span>
    <span style={{fontSize:"13px",color:"#141635"}}>Present code, hand over cash</span>
  </div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>5</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>Retail</span>
    <span style={{color:"#670DE5",fontWeight:"700"}}>→</span>
    <span style={{background:"#EAE4F5",color:"#670DE5",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"700",whiteSpace:"nowrap"}}>OMS</span>
    <span style={{fontSize:"13px",color:"#141635"}}>Confirm deposit + actual amount</span>
  </div>

  <div style={{borderBottom:"1px solid #EEF0F9",padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>6</span>
    <span style={{background:"#EAE4F5",color:"#670DE5",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"700",whiteSpace:"nowrap"}}>OMS</span>
    <span style={{fontSize:"13px",color:"#141635",marginLeft:"4px"}}>Auto-create fiatToCrypto transaction</span>
  </div>

  <div style={{padding:"9px 16px",display:"flex",alignItems:"center",gap:"10px"}}>
    <span style={{color:"#929EBA",fontSize:"11px",fontWeight:"700",minWidth:"16px",textAlign:"right"}}>7</span>
    <span style={{background:"#EAE4F5",color:"#670DE5",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"700",whiteSpace:"nowrap"}}>OMS</span>
    <span style={{color:"#670DE5",fontWeight:"700"}}>→</span>
    <span style={{background:"#EEF0F9",color:"#48526F",padding:"2px 8px",borderRadius:"4px",fontSize:"11px",fontWeight:"600",whiteSpace:"nowrap"}}>App</span>
    <span style={{fontFamily:"'Geist Mono',ui-monospace,monospace",fontSize:"12px",color:"#141635"}}>Webhook: cashIn.completed + transaction.fiatToCrypto.completed</span>
  </div>
</div>

## Prerequisites

Before creating a cash-in, you need:

1. **A customer** with a `cst_` ID who has passed KYC (required for all fiat transactions).
2. **A cash location** with a `loc_` ID, retrieved from `GET /cash-locations`. This is the retail location where the customer will deposit cash. The endpoint requires the query parameters `provider`, `latitude`, and `longitude` to search for nearby locations (for example, `GET /cash-locations?provider=greendot&latitude=38.495133&longitude=-121.505336`).
3. **A destination**: specified via the `destination.wallet` object: an OMS custodial wallet (`wallet`), an external onchain address (`blockchainAddress`), or a saved blockchain address (`externalAccount` with `cpBcAddr_` prefix). The `externalAccount` variant depends on external accounts, which is not yet available in the OMS API.
4. **Webhook subscriptions** configured in the OMS Dashboard for `cashIn.*` and `transaction.fiatToCrypto.*` events.

## How Cash-In Works

Cash-In is a specialized, ephemeral flow for in-person cash deposits. Unlike Deposit Addresses (persistent, reusable, crypto-source), a cash-in generates a one-time deposit code valid for 1 hour. The customer presents the code at a retail location, deposits cash, and OMS auto-converts to crypto.

Key differences from other funding methods:

* **Indicated amount, not exact amount.** You provide an optional `source.indicatedAmount` (defaults to \$100.00, below the provider's `max_transaction`). OMS uses this to generate upfront pricing estimates. The actual deposit amount is determined by how much cash the customer deposits at the counter.
* **Pricing is estimated at creation, finalized after deposit.** The response includes pricing fields inline on the `source` and `destination` objects based on `indicatedAmount`. Once the customer deposits cash, pricing is recalculated on the actual amount.
* **No quote step.** Cash-In auto-creates a transaction when the deposit is received, similar to Deposit Addresses and Virtual Accounts.
* **Both `percentage` and `fixed` developer fees** are supported, since the actual deposit amount isn't known until the customer hands over cash.
* **Gas sponsorship.** Set `sponsorGas: true` to pay gas fees on behalf of the customer. Gas cost appears in `sponsorGasCost` at the top level.

## Step 1: Create a Cash-In Code

```
POST /v0.9/cash-ins
Idempotency-Key: ci_order_789
```

```json theme={null}
{
  "customerId": "cst_01H9Xa...",
  "source": {
    "asset": "usd",
    "indicatedAmount": "200.00"
  },
  "destination": {
    "wallet": {
      "wallet": "wlt_01H9Xb..."
    },
    "asset": "usdc",
    "network": "polygon"
  },
  "cash": {
    "cashLocationId": "loc_01H9Xd...",
    "cashLocationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9MzguNDk1MTMzLGxuZz0tMTIxLjUwNTMzNg=="
  },
  "sponsorGas": false,
  "developerFees": [
    { "type": "percentage", "rate": "0.01", "wallet": "wlt_01H9Xf..." },
    { "type": "fixed", "amount": "1.00", "wallet": "wlt_01H9Xf..." }
  ],
  "metadata": {
    "order_id": "ord_789"
  }
}
```

**Required fields:** `customer`, `source.asset` (always `usd`), `destination` (asset, network, and `wallet` object with one of `wallet`, `blockchainAddress`, or `externalAccount`), `cash.cashLocationId`, `cash.cashLocationReference`.

**`cash.cashLocationReference`** (required): Opaque provider reference for the cash location, obtained from the `locReference` field in the `GET /cash-locations` response.

**`source.indicatedAmount`** (optional): The expected deposit amount. Defaults to `"100.00"` if omitted. Below the provider's `max_transaction` limit (\$500.00). OMS uses this value to generate upfront pricing estimates in the response. The actual deposit amount is determined by how much cash the customer deposits at the location.

**`sponsorGas`** (optional): Set to `true` to have the developer pay gas fees instead of the customer. Defaults to `false`. When enabled, `source.feesDeducted.gas` will be `"0.00"` and the developer-paid gas cost appears in `sponsorGasCost`.

**Developer fees:** Cash-In supports both `percentage` and `fixed` types, unlike Deposit Addresses and Virtual Accounts, which are percentage-only. Each entry may include a `wallet` to direct that fee to a specific wallet.

### Response, `201 Created`

```json theme={null}
{
  "id": "ci_01H9Xy...",
  "status": "pending",
  "customerId": "cst_01H9Xa...",
  "source": {
    "asset": "usd",
    "network": "cash",
    "indicatedAmount": "200.00",
    "amount": null,
    "amountGross": "200.00",
    "amountNet": "192.00",
    "feesDeducted": {
      "total": "8.00",
      "developer": "3.00",
      "oms": "5.00",
      "gas": "0.00"
    }
  },
  "destination": {
    "asset": "usdc",
    "network": "polygon",
    "wallet": {
      "wallet": "wlt_01H9Xb..."
    },
    "amount": null,
    "amountGross": "192.00",
    "amountNet": "192.00",
    "feesDeducted": {
      "total": "0.00",
      "developer": "0.00",
      "oms": "0.00",
      "gas": "0.00"
    }
  },
  "fixedAmountSide": "source",
  "sponsorGas": false,
  "sponsorGasCost": null,
  "rates": {
    "pair": "usd/usdc",
    "exchangeRate": "1.0000",
    "effectiveRate": "0.9600"
  },
  "cash": {
    "cashLocationId": "loc_01H9Xd...",
    "cashLocationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9MzguNDk1MTMzLGxuZz0tMTIxLjUwNTMzNg=="
  },
  "depositInstructions": {
    "code": "483 291",
    "expiresAt": "2026-03-16T19:30:00Z",
    "locationName": "CVS Pharmacy #4521",
    "locationAddress": "123 Main St, New York, NY 10001"
  },
  "developerFees": [
    { "type": "percentage", "rate": "0.01", "wallet": "wlt_01H9Xf..." },
    { "type": "fixed", "amount": "1.00", "wallet": "wlt_01H9Xf..." }
  ],
  "omsFeeSchedule": {
    "feeCurrency": "usd",
    "entries": [
      { "type": "percentage", "rate": "0.02" },
      { "type": "fixed", "amount": "3.00" }
    ]
  },
  "transaction": null,
  "createdAt": "2026-03-16T18:30:00Z",
  "completedAt": null,
  "metadata": {
    "order_id": "ord_789"
  }
}
```

**What to show the customer:**

* `depositInstructions.code`: the code they present at the retail counter ("483 291").
* `depositInstructions.locationName` and `locationAddress`: where to go.
* `depositInstructions.expiresAt`: the code is valid for 1 hour.
* `source.amountGross`, `source.amountNet`, `source.feesDeducted`, `rates`: estimated fee breakdown based on `indicatedAmount` (\$200.00). Show the customer what their fees would look like at this deposit amount.
* `omsFeeSchedule`: the fee structure rules, so the customer understands the cost formula regardless of how much they deposit.

**What's null until deposit:** `source.amount`, `destination.amount`, `transaction`, `completedAt`. Pricing is calculated at creation as estimates based on `indicatedAmount`, then finalized with actual values after the deposit is confirmed.

## Step 2: Customer Deposits Cash

The customer visits the location and presents their code at the counter. This step happens outside OMS, at the retail location's payment terminal. OMS is notified when the deposit is received.

If the code expires before the customer arrives, you can refresh it (see "Refreshing an Expired Code" below).

## Step 3: Deposit Received, Cash-In Completes

Once the retail partner confirms the deposit, OMS calculates fees based on the actual amount, converts USD to the destination crypto, and delivers it. You receive a `cash_in.completed` webhook.

### Webhook, `cash_in.completed`

```json theme={null}
{
  "id": "whk_evt_01H9Xw1...",
  "event": "cash_in.completed",
  "createdAt": "2026-03-16T18:47:00Z",
  "data": {
    "id": "ci_01H9Xy...",
    "status": "completed",
    "customerId": "cst_01H9Xa...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "indicatedAmount": "200.00",
      "amount": "200.00",
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      }
    },
    "destination": {
      "asset": "usdc",
      "network": "polygon",
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "amount": "192.00",
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      }
    },
    "fixedAmountSide": "source",
    "sponsorGas": false,
    "sponsorGasCost": null,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "cash": {
      "cashLocationId": "loc_01H9Xd...",
      "cashLocationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9MzguNDk1MTMzLGxuZz0tMTIxLjUwNTMzNg=="
    },
    "depositInstructions": {
      "code": "483 291",
      "expiresAt": "2026-03-16T19:30:00Z",
      "locationName": "CVS Pharmacy #4521",
      "locationAddress": "123 Main St, New York, NY 10001"
    },
    "developerFees": [
      { "type": "percentage", "rate": "0.01", "wallet": "wlt_01H9Xf..." },
      { "type": "fixed", "amount": "1.00", "wallet": "wlt_01H9Xf..." }
    ],
    "omsFeeSchedule": {
      "feeCurrency": "usd",
      "entries": [
        { "type": "percentage", "rate": "0.02" },
        { "type": "fixed", "amount": "3.00" }
      ]
    },
    "transaction": "txn_01H9Xz...",
    "createdAt": "2026-03-16T18:30:00Z",
    "completedAt": "2026-03-16T18:47:00Z",
    "metadata": {
      "order_id": "ord_789"
    }
  }
}
```

**What changed from the creation response:**

* `status` is now `completed`.
* `source.amount` is populated: the customer deposited \$200.00 (matching `indicatedAmount` in this example).
* `destination.amount` is populated: 192.00 USDC after fees.
* `source.amountGross`, `source.amountNet`, `source.feesDeducted`, `destination.amountGross`, `destination.amountNet`, and `destination.feesDeducted` are updated with final values based on the actual deposit amount (were estimated from `indicatedAmount` at creation).
* `transaction` links to the auto-created transaction (the `txn_` ID).
* `completedAt` marks when the deposit was confirmed.

**Example fee breakdown** for a $200.00 deposit with the developer fees and `omsFeeSchedule` shown above (1% + $1.00 developer, 2% + \$1.00 OMS). Actual fees on your account will follow whatever rates you and OMS have configured.

| Fee                       | Calculation                | Amount          |
| ------------------------- | -------------------------- | --------------- |
| Developer percentage (1%) | \$200.00 × 0.01            | \$2.00          |
| Developer fixed           | flat                       | \$1.00          |
| **Total developer fee**   |                            | **\$3.00**      |
| OMS percentage (2%)       | \$200.00 × 0.02            | \$4.00          |
| OMS fixed                 | flat                       | \$1.00          |
| **Total OMS fee**         |                            | **\$5.00**      |
| **Total fees**            |                            | **\$8.00**      |
| **Crypto delivered**      | ($200.00 − $8.00) × 1.0000 | **192.00 USDC** |

## Step 4: Auto-Created Transaction

When the cash-in completes, OMS auto-creates a fiat-to-crypto transaction. This transaction follows the standard processing → completed lifecycle and fires the usual `transaction.fiatToCrypto.*` webhook events.

### Webhook, `transaction.fiatToCrypto.processing`

```json theme={null}
{
  "id": "whk_evt_01H9Xw2...",
  "event": "transaction.fiatToCrypto.processing",
  "createdAt": "2026-03-16T18:47:05Z",
  "data": {
    "id": "txn_01H9Xz...",
    "object": "transaction",
    "type": "fiatToCrypto",
    "status": "processing",
    "subStatus": "processing.fundsPulled",
    "customerId": "cst_01H9Xa...",
    "quoteId": null,
    "depositAddress": null,
    "virtualAccount": null,
    "cashIn": "ci_01H9Xy...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "destination": {
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "asset": "usdc",
      "network": "polygon",
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "fixedAmountSide": "source",
    "sponsorGasCost": null,
    "sponsorGas": false,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "estimatedArrival": null,
    "error": null,
    "metadata": {
      "order_id": "ord_789"
    },
    "createdAt": "2026-03-16T18:47:05Z",
    "updatedAt": "2026-03-16T18:47:05Z"
  }
}
```

**Key fields on the auto-created transaction:**

* `quote: null`: auto-created transactions skip the quote step.
* `cashIn: "ci_01H9Xy..."`: top-level field linking this transaction back to the originating cash-in.
* `source.network: "cash"`: indicates the source was a cash deposit.
* `source.txHash: null`: there's no blockchain transaction on the source side (it's cash).
* `destination.amountGross: "192.00"`: already calculated from the deposit amount minus all fees.

### Webhook, `transaction.fiatToCrypto.completed`

```json theme={null}
{
  "id": "whk_evt_01H9Xw3...",
  "event": "transaction.fiatToCrypto.completed",
  "createdAt": "2026-03-16T18:48:30Z",
  "data": {
    "id": "txn_01H9Xz...",
    "object": "transaction",
    "type": "fiatToCrypto",
    "status": "completed",
    "subStatus": null,
    "customerId": "cst_01H9Xa...",
    "quoteId": null,
    "depositAddress": null,
    "virtualAccount": null,
    "cashIn": "ci_01H9Xy...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "destination": {
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "asset": "usdc",
      "network": "polygon",
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      },
      "txHash": "0x4c8d2e9f1a3b5c7d0e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4c6d"
    },
    "fixedAmountSide": "source",
    "sponsorGasCost": null,
    "sponsorGas": false,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "estimatedArrival": null,
    "error": null,
    "metadata": {
      "order_id": "ord_789"
    },
    "createdAt": "2026-03-16T18:47:05Z",
    "updatedAt": "2026-03-16T18:48:30Z"
  }
}
```

**What changed from the `processing` webhook:**

* `status` is now `completed` and `subStatus` is `null`.
* `destination.txHash` is populated with the onchain transaction hash for the crypto delivery.
* `updatedAt` reflects the completion time.

At this point the flow is done. The customer deposited $200.00 cash at CVS Pharmacy #4521, your $3.00 developer fee was collected, OMS took a \$5.00 platform fee, and 192.00 USDC was delivered to wallet `wlt_01H9Xb...` on Polygon.

## Refreshing an Expired Code

If the customer doesn't arrive before the code expires, refresh it to generate a new code with a new 1-hour window. The previous code is invalidated.

```
POST /v0.9/cash-ins/ci_01H9Xy.../refresh
Idempotency-Key: ci_refresh_789_2
```

### Response

```json theme={null}
{
  "id": "ci_01H9Xy...",
  "status": "pending",
  "customerId": "cst_01H9Xa...",
  "source": {
    "asset": "usd",
    "network": "cash",
    "indicatedAmount": "200.00",
    "amount": null,
    "amountGross": "200.00",
    "amountNet": "192.00",
    "feesDeducted": {
      "total": "8.00",
      "developer": "3.00",
      "oms": "5.00",
      "gas": "0.00"
    }
  },
  "destination": {
    "asset": "usdc",
    "network": "polygon",
    "wallet": {
      "wallet": "wlt_01H9Xb..."
    },
    "amount": null,
    "amountGross": "192.00",
    "amountNet": "192.00",
    "feesDeducted": {
      "total": "0.00",
      "developer": "0.00",
      "oms": "0.00",
      "gas": "0.00"
    }
  },
  "fixedAmountSide": "source",
  "sponsorGas": false,
  "sponsorGasCost": null,
  "rates": {
    "pair": "usd/usdc",
    "exchangeRate": "1.0000",
    "effectiveRate": "0.9600"
  },
  "cash": {
    "cashLocationId": "loc_01H9Xd...",
    "cashLocationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9MzguNDk1MTMzLGxuZz0tMTIxLjUwNTMzNg=="
  },
  "depositInstructions": {
    "code": "917 042",
    "expiresAt": "2026-03-16T20:30:00Z",
    "locationName": "CVS Pharmacy #4521",
    "locationAddress": "123 Main St, New York, NY 10001"
  },
  "developerFees": [
    { "type": "percentage", "rate": "0.01", "wallet": "wlt_01H9Xf..." },
    { "type": "fixed", "amount": "1.00", "wallet": "wlt_01H9Xf..." }
  ],
  "omsFeeSchedule": {
    "feeCurrency": "usd",
    "entries": [
      { "type": "percentage", "rate": "0.02" },
      { "type": "fixed", "amount": "3.00" }
    ]
  },
  "transaction": null,
  "createdAt": "2026-03-16T18:30:00Z",
  "completedAt": null,
  "metadata": {
    "order_id": "ord_789"
  }
}
```

**What changed:** `depositInstructions.code` is now `"917 042"` (new code) and `expiresAt` is extended by another hour. Everything else stays the same.

**Constraints:** Refresh can only be called while the cash-in is in `pending` status. If the cash-in has already `completed` or `expired` past the refresh window, the call returns `422 Unprocessable`.

## Code Expiration

If the code expires without a deposit, OMS fires a `cash_in.expired` webhook.

### Webhook, `cash_in.expired`

```json theme={null}
{
  "id": "whk_evt_01H9Xw4...",
  "event": "cash_in.expired",
  "createdAt": "2026-03-16T19:30:00Z",
  "data": {
    "id": "ci_01H9Xy...",
    "status": "expired",
    "customerId": "cst_01H9Xa...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "indicatedAmount": "200.00",
      "amount": null,
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      }
    },
    "destination": {
      "asset": "usdc",
      "network": "polygon",
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "amount": null,
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      }
    },
    "fixedAmountSide": "source",
    "sponsorGas": false,
    "sponsorGasCost": null,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "cash": {
      "cashLocationId": "loc_01H9Xd...",
      "cashLocationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9MzguNDk1MTMzLGxuZz0tMTIxLjUwNTMzNg=="
    },
    "depositInstructions": {
      "code": "483 291",
      "expiresAt": "2026-03-16T19:30:00Z",
      "locationName": "CVS Pharmacy #4521",
      "locationAddress": "123 Main St, New York, NY 10001"
    },
    "transaction": null,
    "createdAt": "2026-03-16T18:30:00Z",
    "completedAt": null,
    "metadata": {
      "order_id": "ord_789"
    }
  }
}
```

An expired cash-in is terminal, no transaction is created, no money moves. If the customer still wants to deposit cash, create a new cash-in.

## Polling

You can poll the cash-in status at any time:

```
GET /v0.9/cash-ins/ci_01H9Xy...
```

Or list all cash-ins for a customer, optionally filtered by status:

```
GET /v0.9/cash-ins?customer=cst_01H9Xa...&status=pending
```

## Failure Handling

Cash-In failures can happen at two levels:

**Cash-In level:** The code expires before the customer deposits cash. The cash-in moves to `expired` and no transaction is created. No money moved, no refund needed.

**Transaction level:** The cash deposit is received but crypto delivery fails. The auto-created transaction moves to `failed` and OMS initiates a refund. You'll receive a `transaction.fiatToCrypto.failed` webhook:

```json theme={null}
{
  "id": "whk_evt_01H9Xw5...",
  "event": "transaction.fiatToCrypto.failed",
  "createdAt": "2026-03-16T18:50:00Z",
  "data": {
    "id": "txn_01H9Xz...",
    "object": "transaction",
    "type": "fiatToCrypto",
    "status": "failed",
    "subStatus": "failed.refundPending",
    "customerId": "cst_01H9Xa...",
    "quoteId": null,
    "cashIn": "ci_01H9Xy...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "destination": {
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "asset": "usdc",
      "network": "polygon",
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "fixedAmountSide": "source",
    "sponsorGasCost": null,
    "sponsorGas": false,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "error": {
      "code": "on_chain_revert",
      "message": "Delivery transaction reverted onchain"
    },
    "metadata": {
      "order_id": "ord_789"
    },
    "createdAt": "2026-03-16T18:47:05Z",
    "updatedAt": "2026-03-16T18:50:00Z"
  }
}
```

Cash refunds are handled outside OMS at the retail location. The `refundPending` subStatus indicates OMS has initiated the refund process.

## Compliance Review

If a transaction triggered by a cash-in is flagged for compliance review, you'll receive a developer-only webhook. Do NOT surface this to the customer.

```json theme={null}
{
  "id": "whk_evt_01H9Xw6...",
  "event": "transaction.fiatToCrypto.underReview",
  "createdAt": "2026-03-16T18:48:00Z",
  "data": {
    "id": "txn_01H9Xz...",
    "object": "transaction",
    "type": "fiatToCrypto",
    "status": "processing",
    "subStatus": "processing.underReview",
    "customerId": "cst_01H9Xa...",
    "quoteId": null,
    "cashIn": "ci_01H9Xy...",
    "source": {
      "asset": "usd",
      "network": "cash",
      "amountGross": "200.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "8.00",
        "developer": "3.00",
        "oms": "5.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "destination": {
      "wallet": {
        "wallet": "wlt_01H9Xb..."
      },
      "asset": "usdc",
      "network": "polygon",
      "amountGross": "192.00",
      "amountNet": "192.00",
      "feesDeducted": {
        "total": "0.00",
        "developer": "0.00",
        "oms": "0.00",
        "gas": "0.00"
      },
      "txHash": null
    },
    "fixedAmountSide": "source",
    "sponsorGasCost": null,
    "sponsorGas": false,
    "rates": {
      "pair": "usd/usdc",
      "exchangeRate": "1.0000",
      "effectiveRate": "0.9600"
    },
    "metadata": {
      "order_id": "ord_789"
    },
    "createdAt": "2026-03-16T18:47:05Z",
    "updatedAt": "2026-03-16T18:48:00Z"
  }
}
```

The transaction remains in `processing` during review. Once resolved, it proceeds to `completed` or `failed`.

## Summary: Webhook Events

### Cash-In Events

| Event               | When                                   |
| ------------------- | -------------------------------------- |
| `cash_in.completed` | Cash deposited and converted to crypto |
| `cash_in.expired`   | Code expired without a deposit         |

### Transaction Events (auto-created)

| Event                                      | When                                     |
| ------------------------------------------ | ---------------------------------------- |
| `transaction.fiatToCrypto.processing`      | Cash received, crypto delivery underway  |
| `transaction.fiatToCrypto.completed`       | Crypto delivered to destination          |
| `transaction.fiatToCrypto.failed`          | Crypto delivery failed, refund initiated |
| `transaction.fiatToCrypto.refundCompleted` | Refund completed                         |
| `transaction.fiatToCrypto.underReview`     | Under compliance review (developer-only) |

## Key Points

* **Indicated amount for upfront pricing.** Pass `source.indicatedAmount` (optional, defaults to \$100.00, below provider's `max_transaction`). OMS returns estimated pricing at creation; final pricing is calculated when the customer deposits.
* **Show pricing estimates upfront.** The inline pricing fields (`source.amountGross`, `source.amountNet`, `source.feesDeducted`, `destination.amountGross`, `destination.amountNet`, `destination.feesDeducted`, and `rates`) in the creation response give the customer a clear picture of fees and rates based on `indicatedAmount`. `omsFeeSchedule` shows the raw fee rules.
* **Gas sponsorship.** Set `sponsorGas: true` to pay gas fees on behalf of the customer. Gas cost appears in `sponsorGasCost`.
* **Codes expire in 1 hour.** Call `POST /cash-ins/{id}/refresh` to generate a new code if the customer needs more time. Only works while `status` is `pending`.
* **Cash-In is single-use.** Once a deposit is received or the code expires, the cash-in is terminal. Create a new one for the next deposit.
* **Two layers of webhooks.** You receive both `cashIn.*` events (for the cash-in resource itself) and `transaction.fiatToCrypto.*` events (for the auto-created transaction). Design your webhook handler to process both.
* **`source.txHash` is always null.** The source is a physical cash deposit, not a blockchain transaction.
* **Both percentage and fixed developer fees.** Unlike Deposit Addresses and Virtual Accounts (percentage-only), cash-in supports both fee types since the amount isn't known until deposit.
* **Three destination options.** Cash-In uses the `destination.wallet` object with one of `wallet` (OMS custodial wallet), `blockchainAddress` (external onchain address), or `externalAccount` (saved blockchain address, `cpBcAddr_` prefix).
