Skip to main content
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 before you begin.
Cash-in flow
1AppOMSPOST /cash-ins (destination, location, indicatedAmount)
2OMSApp{depositCode: “XXXX-XXXX”, expiresAt}
3AppCustomerShow deposit code + nearby location
4CustomerRetailPresent code, hand over cash
5RetailOMSConfirm deposit + actual amount
6OMSAuto-create fiatToCrypto transaction
7OMSAppWebhook: cashIn.completed + transaction.fiatToCrypto.completed

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
{
  "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

{
  "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

{
  "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.00depositwiththedeveloperfeesandomsFeeScheduleshownabove(1200.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.
FeeCalculationAmount
Developer percentage (1%)$200.00 × 0.01$2.00
Developer fixedflat$1.00
Total developer fee$3.00
OMS percentage (2%)$200.00 × 0.02$4.00
OMS fixedflat$1.00
Total OMS fee$5.00
Total fees$8.00
Crypto delivered(200.00200.00 − 8.00) × 1.0000192.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

{
  "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

{
  "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

{
  "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

{
  "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:
{
  "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.
{
  "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

EventWhen
cash_in.completedCash deposited and converted to crypto
cash_in.expiredCode expired without a deposit

Transaction Events (auto-created)

EventWhen
transaction.fiatToCrypto.processingCash received, crypto delivery underway
transaction.fiatToCrypto.completedCrypto delivered to destination
transaction.fiatToCrypto.failedCrypto delivery failed, refund initiated
transaction.fiatToCrypto.refundCompletedRefund completed
transaction.fiatToCrypto.underReviewUnder 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).