The only endpoint that creates a member balance credit without an existing ledger debit. All six controls are mandatory.
Reporting Deposits
POST /v1/deposits
x-idempotency-key: <UUID>
{
"external_member_id": "u_88123",
"asset": "USDT",
"amount": "100.00",
"reference": "<你的入金流水号>",
"network": "BSC",
"txid": "0x…",
"from_address": "0x…",
"to_address": "0x…"
}
You report the deposit; we record it. This is the only endpoint that creates a member balance credit without an existing ledger debit. None of its controls is relaxed simply because the request comes from you.
Idempotency: two keys for two different risks
| Protects against | Window | |
|---|---|---|
x-idempotency-key (header) | Network retries | 24 hours |
reference (required body field) | Crediting the same deposit twice | Permanent |
Use your system's unique identifier for that deposit as reference, not a random UUID.
⚠ After 24 hours, only
referencestill prevents a duplicate credit.A random
referencecan turn a next-day recovery job into a second credit,increasing the member's balance without a second deposit.
When a request is replayed
- HTTP 200, rather than 201 for the first credit.
replayed: true- The response contains the stored record, not the values submitted in the retry.
⚠ If you retry the same
referencewith a differentx-idempotency-keyand a changed
txid, the ledger and order row are not overwritten; the first record remains authoritative.Echoing the new inputs would incorrectly suggest that the new txid had been accepted,
leaving reconciliation to discover a different stored value later.
When
replayed: true, reconcile against the returned on-chain fields. Do not assume they match your submitted values.
Six controls
| # | Control | On failure or replay |
|---|---|---|
| ① | Signature verification | 401; cannot be disabled |
| ② | Idempotency, including your transaction reference | 200 + replayed: true |
| ③ | Per-transaction limit | 400 limit_exceeded, limit_type: "single" |
| ④ | Asset allowlist; reject all unknown assets | 400 asset_not_allowed |
| ⑤ | Standard platform risk and eligibility checks | 400 request_rejected |
| ⑥ | Full audit trail | — |
⚠ Control ③ is also a signal: an unusually large reported deposit may be the first observable sign
that a merchant system has been compromised.
⚠ Control ④ rejects the deposit rather than posting it to a suspense account.
Queuing an unknown asset would introduce funds of unknown origin into the ledger.
⚠ Control ⑤ means deposit reporting does not bypass risk controls.
Deposits for blocked, blacklisted or frozen members are rejected before posting.
Exceeding a daily cumulative limit also returns limit_exceeded, with limit_type: "daily".
Amounts are fixed-point strings
"amount": "100.00" ✓
"amount": 100.00 ✗ JSON number
Use the asset's ledger_scale, available from GET /v1/assets.
⚠ On-chain assets with 18 decimal places exceed
2^53. Parsing their amounts as numbers loses precisionwithout an error: digits are silently lost.
On-chain traceability fields
network / txid / from_address / to_address are all optional, with one constraint:
⚠ Supplying any of the other three fields without
networkreturns 400.A txid without a network cannot reliably identify a transaction for reconciliation.
Maximum lengths: network ≤ 32, txid ≤ 128, addresses ≤ 200. Both network and asset are normalized to uppercase.
We strongly recommend providing all four fields. They are what connect a ledger record to the on-chain transaction when investigating a problem.
After reporting
- The member balance increases immediately; there is no asynchronous or intermediate state.
- A
deposit.creditedevent is emitted. - Your custody balance increases accordingly; reconcile it using custody reconciliation.