Collect deposits
The Quickstart walks the happy path once. This guide is the same flow with the decisions and the failure modes: how to organise wallets, what each status does to your balance, and how to reconcile so a missed webhook never becomes a missed credit.
The model in one paragraph
Section titled “The model in one paragraph”A wallet is a dedicated deposit address on one chain, derived for your workspace and watched permanently. Your end-user sends funds to it; CowriePay detects the transaction, tracks its confirmations, credits your workspace, then consolidates the funds to custody. You never handle keys or gas; you consume webhooks and read the API.
Wallet strategy: per order, per user, or both
Section titled “Wallet strategy: per order, per user, or both”- A wallet per order is the safest attribution: whatever arrives on the address belongs to that
order, and
external_refcarries your own opaque id for it. - A wallet per end-user suits balance-style products (the user tops up whenever they like).
Attach wallets to a customer (
customer_idat creation) to group them: attribution is first-class and queryable, while balances stay at the workspace level. Catalogue on the Customers reference. - Never put personal data in
external_ref; it is your opaque id, nothing else.
Addresses are watched for as long as they exist, so a late payment to an old order’s address is
still detected and credited; your external_ref mapping is what tells you what it was for.
Every status, its webhook, and what it does to your balance
Section titled “Every status, its webhook, and what it does to your balance”| Status | Meaning | Webhook | Balance effect |
|---|---|---|---|
DETECTED |
Seen on-chain, below the confirmation threshold | DEPOSIT_DETECTED |
pending increases |
CONFIRMING |
Accumulating confirmations | (none per confirmation) | none |
CONFIRMED |
Threshold reached; credit your customer now | DEPOSIT_CONFIRMED |
none yet |
SWEPT |
Consolidated to custody; fee settled | DEPOSIT_SWEPT (with the fee breakdown) |
pending decreases, available increases by the net |
FLAGGED |
Held for compliance review; do not credit | DEPOSIT_FLAGGED |
stays in pending, never credited while held |
REJECTED |
Review concluded against the deposit; funds stay frozen | (no event; terminal) | removed from pending |
Two decisions fall out of this table:
- Credit your end-customer at
CONFIRMED, never atDETECTED(a detected transaction can still disappear in a reorganisation, see On-chain concepts). Read the threshold off the deposit’srequired_confirmations. - Your spendable balance moves at
SWEPT, when the net lands inavailableand thefeeobject in the payload gives yougross_amount,fee_amountandnet_amountfor reconciliation. BetweenCONFIRMEDandSWEPTthe funds are safe but sit inpending; if your product pays out immediately after crediting, account for that window.
A FLAGGED deposit is not an error in your integration: hold the credit, surface “under review” to
your user if relevant, and contact support if it persists. It resolves either to the normal flow
(released) or to REJECTED.
Reconcile with webhooks first, polling second
Section titled “Reconcile with webhooks first, polling second”Webhooks are the primary feed and they are delivery-guaranteed with retries; the Webhooks guide covers signature verification and the deduplication contract (the delivery id is stable across retries; the deposit id is your business key).
Polling is the safety net, not the integration: GET /v2/transactions/deposits filters by status
and pages through history, and each item carries its fee_record (null until swept). A sane
reconciliation habit:
nightly (or hourly), per open order: deposits = GET /v2/transactions/deposits?status=CONFIRMED for each deposit not yet processed in your system: process it exactly as the webhook handler would (same code path)Make the webhook handler and the reconciler share one idempotent processing function, keyed on
deposit_id. Processing a deposit twice must be a no-op; that single property absorbs crashes,
replays and reconciliation overlaps at once.
The cases that surprise integrators
Section titled “The cases that surprise integrators”- Small deposits wait. Below the per-asset consolidation minimum, a deposit stays
CONFIRMED(credited topending, your customer creditable) but is not yet swept; it consolidates once the address’s accumulated balance crosses the floor. The floors are in On-chain concepts. - The fee is settled at consolidation, not at confirmation.
fee_recordon the deposit is null untilSWEPT; do not reconcile fees before then. - One deposit can arrive in several transactions. Each on-chain transaction is its own deposit record with its own lifecycle. If your product expects an exact amount, sum the confirmed deposits on the wallet rather than expecting one record.
What next
Section titled “What next”- Send withdrawals: the outbound half, and the security wall that comes with it.
- Webhooks: the delivery contract your status handling relies on.
- The sandbox and the faucet: rehearse all of the above against the real testnet.