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
1App→OMSPOST /cash-ins (destination, location, indicatedAmount)
2OMS→App{depositCode: “XXXX-XXXX”, expiresAt}
3App→CustomerShow deposit code + nearby location
4Customer→RetailPresent code, hand over cash
5Retail→OMSConfirm deposit + actual amount
6OMSAuto-create fiatToCrypto transaction
7OMS→AppWebhook: cashIn.completed + transaction.fiatToCrypto.completed
Prerequisites
Before creating a cash-in, you need:
- A customer with a
cst_ ID who has passed KYC (required for all fiat transactions).
- 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).
- 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.
- 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.00depositwiththedeveloperfeesand‘omsFeeSchedule‘shownabove(11.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
{
"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
| 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).