CashMine practical task API =========================== A test backend for the CashMine React Native practical task. All data is made up and nothing here moves real money. Treat it like a real remote server: requests can be slow, and any request can fail. Base URL: https://task-api.cashmine.io Authentication -------------- Send your token from the task email on every /v1 request: Authorization: Bearer Your data belongs to your token only. It starts fresh with your first request and includes about 30 days of history. The token stops working 30 minutes after your task ends. Conventions ----------- - JSON in and out. Times are ISO 8601 strings in UTC. - Amounts are decimal strings in the asset's own unit, for example "0.0005" (BTC). They are never JSON numbers. Each asset allows at most `decimals` decimal places. - CORS is open, so Expo web works too. Errors ------ { "error": { "code": "VALIDATION", "message": "...", "field": "amount" } } HTTP code meaning 400 VALIDATION the request is invalid; `field` names the field when there is one 401 UNAUTHORIZED token missing, invalid or expired 404 NOT_FOUND unknown endpoint or id 409 IDEMPOTENCY_MISMATCH an Idempotency-Key was reused with a different body 429 RATE_LIMITED too many requests; wait `retryAfterMs` (also the Retry-After header, in seconds) 500 SERVER temporary server error 503 SERVER temporary server error 504 TIMEOUT the server did not finish in time; the outcome is unknown Rate limits apply per token. GET /v1/balances ---------------- { "asOf": "2026-10-20T08:01:15.000Z", "items": [ { "asset": "USDT", "decimals": 6, "available": "820.413207", "pending": "50.12", "claiming": "0", "usdPrice": "1.0002" } ] } - available: can be claimed now - pending: payback accrued but not yet confirmed; it becomes available once confirmed - claiming: the amount in claims that have not completed yet - usdPrice: the price of one unit in USD Balances are snapshots, recomputed every 15 seconds. `asOf` is the time of the snapshot, so a claim you just created may not show up until the next one. GET /v1/activity?limit=20&cursor=... ------------------------------------ History, newest first. `limit` is 1 to 50 (default 20). Pass `nextCursor` as `cursor` to get the next page; `nextCursor` is null on the last page. { "items": [ { "id": "act_...", "type": "accrual", "asset": "USDT", "amount": "9.81", "status": "confirmed", "exchange": "Binance", "createdAt": "...", "relatedId": null } ], "nextCursor": "..." } - type: accrual (payback earned on an exchange), reversal (an earlier accrual taken back by the exchange; relatedId is that accrual's id) or claim (relatedId is the claim id) - amount: signed; negative for reversals and claims - status: accrual pending | confirmed; reversal confirmed; claim pending | completed | failed GET /v1/claim-options?asset=ETH ------------------------------- { "asset": "ETH", "minAmount": "0.01", "fee": "0.0012", "destinations": [ { "id": "dest_wallet", "label": "Wallet 0x8f3e…a91c" } ] } The fee is taken from the claimed amount: the user receives amount minus fee. POST /v1/claims --------------- Headers: Idempotency-Key: <1 to 100 characters, required; a UUID works> Body: { "asset": "ETH", "amount": "0.5", "destinationId": "dest_wallet" } Rules: minAmount <= amount <= available, and at most `decimals` decimal places. `available` is checked live, not against the last snapshot. 201 returns a claim. Its amount leaves `available` at once and is counted in `claiming` until the claim settles. Repeating a request with the same Idempotency-Key and the same body returns the original claim (200, header `Idempotent-Replayed: true`) and never creates a second claim, even if the first response was lost. The same key with a different body returns 409. Claim: { "id": "clm_...", "asset": "ETH", "amount": "0.5", "fee": "0.0012", "receiveAmount": "0.4988", "destinationId": "dest_wallet", "status": "pending", "failureReason": null, "createdAt": "...", "updatedAt": "..." } GET /v1/claims/{id} ------------------- Returns the claim. A pending claim settles within about 20 seconds, to completed or failed. When a claim fails, its amount returns to available and failureReason says why.