# Dofamine — crypto payment processing for merchants > Accept USDT and USDC on TRON, Ethereum, Arbitrum One and TON. Every invoice gets its own deposit address; confirmed payments are credited to the merchant balance, from which the merchant pays out, refunds and withdraws. REST API v1, signed webhooks, hosted or embedded checkout. This file is a short summary for coding agents. The full reference is authoritative: - API reference: https://app.dofamine.app/docs - OpenAPI document (public, no key): https://app.dofamine.app/api/openapi - System status: https://app.dofamine.app/status - Support: support@dofamine.app ## Access - Apply at https://dofamine.app/#lead-intake. Production API keys are issued after business verification (KYB). - All keys are live (`pk_live_…`). There is no sandbox and no test network: test with small live payments. - Every call that needs a key sends it as `Authorization: Bearer pk_live_…`. Keys carry scopes (`checkout:write`, `checkout:read`, `payouts:write`, `refunds:write`, `swaps:write`, `settlement:read`, …); a missing scope is `403 insufficient_scope`. - Base URL: `https://app.dofamine.app/api/v1`. JSON in, JSON out. ## Accept a payment 1. On your server, create a checkout session: ```bash curl -X POST https://app.dofamine.app/api/v1/checkout/sessions \ -H "Authorization: Bearer $DOFAMINE_API_KEY" \ -H "Idempotency-Key: order-1042" \ -H "Content-Type: application/json" \ -d '{ "amount": 125000, "currency": "USD", "successUrl": "https://shop.example/paid", "cancelUrl": "https://shop.example/cancelled", "expiresInMinutes": 60, "metadata": { "orderId": "order_1042" } }' ``` `amount` is an integer in minor units of the invoice currency (125000 = 1,250.00 USD). `expiresInMinutes` is 1–720. The `201` answer carries `id`, `kind` (`invoice`), `checkoutUrl`, `expiresAt` and `status` (`open`). 2. Send the payer to `checkoutUrl`, or embed the checkout on your page: ```html
``` Embedding works only on origins allowlisted for your account. 3. Fulfil the order on the `payment.succeeded` webhook, not on the payer's browser coming back. As a fallback, poll `GET /api/v1/checkout/crypto-status/{sessionId}` until the answer has `isFinal: true`. Other outcomes arrive as `payment.partial` (underpayment), `payment.failed` and `payment.needs_manual_review`. Overpayments up to double the invoice amount are credited to the merchant balance automatically; larger ones go to review. ## Webhooks - Register the endpoint in the dashboard (Webhooks) and subscribe it to events. The endpoint secret (`whsec_…`) is shown once. - Body: `{ "event": "payment.succeeded", "mode": "live", "data": { … }, "createdAt": "…" }`. - Verify before any side effect: `X-Dofamine-Signature-V1` = hex(HMAC-SHA256(secret, `X-Dofamine-Timestamp` + "." + raw body bytes)). Compare in constant time and reject timestamps more than 300 seconds from your clock; answer `401` on failure. - `X-Dofamine-Delivery` is the same on every retry of one event: use it to deduplicate. Retries happen on network errors, `5xx`, `408` and `429`. - Main events: `payment.succeeded`, `payment.partial`, `payment.failed`, `payment.needs_manual_review`, `deposit.credited`, `payout.created`, `payout.confirmed`, `payout.failed`, `payout.rejected`, `swap.completed`, `swap.failed`, `statement.monthly_ready`. The full list is in the reference. ## Permanent top-up addresses - `POST /api/v1/crypto/payer-addresses` with `{ "playerRef": "user_88412", "network": "trc20" }` returns a permanent USDT address for that user and network; a repeat returns the same address. Live networks for top-up addresses: `trc20`, `erc20`, `arbitrum` (not TON). - Deposits pass screening before they are credited; amounts below the top-up minimum and deposits from flagged senders are held for review. - Or create a checkout session with `"kind": "topup"` and `playerRef` (no `amount`): the payer gets the address on the hosted checkout. - `playerRef` is your opaque user reference. Personal data is forbidden in it. ## Payouts - `POST /api/v1/crypto/payouts` (requires `Idempotency-Key`): `{ "playerRef": "user_88412", "network": "tron", "asset": "USDT", "amount": "25.50", "address": "T…", "feeSource": "balance" }`. `playerRef` (your recipient reference) is required. `amount` is a decimal string in units of the asset. `feeSource` is `balance` (you pay the network fee) or `amount` (deducted from the payout). - Payout and transfer networks: `tron`, `ethereum`. Every payout passes screening, limits and the approval policy of the account. - `GET /api/v1/crypto/payouts/{id}` for status; `GET`/`PUT /api/v1/crypto/payouts/limits` for per-recipient limits. ## Transfers between networks `POST /api/v1/crypto/swaps` creates an order with a quote; `POST /api/v1/crypto/swaps/{id}/confirm` confirms the rate; `GET /api/v1/crypto/swaps/{id}` reads it. Only verified routes are offered, subject to availability and minimum amounts. ## Refunds `POST /api/v1/crypto/refunds` creates a refund for a payment (TRON, Ethereum, Arbitrum One; not TON); it is sent after approval in the dashboard with 2FA. `GET /api/v1/crypto/refunds` lists refunds. A refund goes to the `refundAddress` given when the session was created, or to an address you name with a reason; without either it is refused (the session answer shows `refundAvailable`). The payer receives the credited amount minus the network costs of the refund; the processing fee is not returned. ## Statements `GET /api/v1/settlement/statement` returns a statement for a period (scope `settlement:read`). ## Idempotency and limits - `Idempotency-Key`: 8–255 characters, one per logical operation. Same key and same body → the stored answer with `idempotent-replayed: true`; same key and a different body → `422`. - 100 calls per minute per key by default. `429` carries `Retry-After`. ## Networks - Acceptance: USDT on TRON (TRC-20), Ethereum (ERC-20), Arbitrum One and TON (Jetton); USDC on Ethereum and Arbitrum One. On TON: invoices only (no top-up addresses, payouts or refunds yet). - Confirmations before an invoice is paid: TRON 19 blocks, Ethereum 12, Arbitrum One 500, TON 1. - Payouts and transfers: TRON and Ethereum. - Fees: a percentage of each payment agreed at onboarding, with a minimum fee per payment that depends on the network.