Cryptopaid API Docs
Centralized crypto payment gateway for all your projects. One API, multiple stores, provider-agnostic.
Documentación de Cryptopaid API
Pasarela de pagos crypto centralizada para todos tus proyectos. Una API, múltiples tiendas, sin dependencia de proveedor.
Introduction Introducción
Cryptopaid is a self-hosted API that lets your projects accept cryptocurrency deposits without integrating directly with any payment provider (OxaPay, NowPayments, etc.).
When the payment provider changes or breaks, you update only Cryptopaid — your projects keep calling the same endpoints and receiving the same webhooks.
Cryptopaid es una API auto-alojada que permite a tus proyectos aceptar depósitos de criptomonedas sin integrarse directamente con ningún proveedor de pagos (OxaPay, NowPayments, etc.).
Cuando el proveedor cambia o falla, solo actualizas Cryptopaid — tus proyectos siguen llamando a los mismos endpoints y recibiendo los mismos webhooks.
Authentication Autenticación
All requests must include an Authorization header with the store API key:
Todas las solicitudes deben incluir el header Authorization con la API key de la tienda:
Authorization: Api-Key cp_live_xxxxxxxxxxxxxxxxxxxx
Quickstart
- Create a Provider Account in Admin — enter OxaPay credentials (
merchant_key,general_key,payout_key) and payout settings. - Create a Store — link it to the Provider Account, copy the API key.
- Add deposit settings on the Store (
auto_convert_to,reuse_open_deposit,revoke_after_hours). - Set
webhook_urlon the store to receive payment confirmations. - Call
POST /api/v1/deposits/from your project. - Show the
addressandqr_codeto your user. - Wait for the
deposit.confirmedwebhook — then credit your user's balance. - For affiliate payouts: call
POST /api/v1/withdrawals/affiliate/. - For auto-sweep: enable
auto_payout_enabledon the Provider Account and configure external cron.
- Crea una Provider Account en Admin — credenciales OxaPay y configuración de retiros.
- Crea una Store — vincúlala a la Provider Account, copia la API key.
- Configura depósitos en la Store (
auto_convert_to,reuse_open_deposit,revoke_after_hours). - Establece
webhook_urlen la tienda para recibir confirmaciones. - Llama a
POST /api/v1/deposits/desde tu proyecto. - Muestra
addressyqr_codeal usuario. - Espera el webhook
deposit.confirmed— acredita el saldo. - Para pagar afiliados:
POST /api/v1/withdrawals/affiliate/. - Para auto-sweep: activa
auto_payout_enableden la Provider Account y configura el cron externo.
import requests
headers = {"Authorization": "Api-Key cp_live_xxxx"}
resp = requests.post(
"https://your-cryptopaid.up.railway.app/api/v1/deposits/",
headers=headers,
json={
"external_user_id": "user_42",
"network": "TRC20",
"currency": "USDT",
}
)
deposit = resp.json()
# Show deposit["address"] and deposit["qr_code"] to your user# Muestra deposit["address"] y deposit["qr_code"] a tu usuario
Create Deposit Crear Depósito
Request body
Cuerpo de la solicitud
| Field | Campo | Type | Tipo | Required | Requerido | Description | Descripción |
|---|---|---|---|---|---|---|---|
| external_user_id | string | required | Your internal user identifier. | Tu identificador interno de usuario. | |||
| network | string | required | Network code: TRC20, ERC20, BTC, etc. |
Código de red: TRC20, ERC20, BTC, etc. |
|||
| currency | string | optional | Token currency (required for multi-token networks like ERC20). | Moneda del token (requerida para redes multi-token como ERC20). | |||
| external_reference | string | optional | Your own order/reference ID. | Tu propio ID de orden/referencia. | |||
| metadata | object | optional | Arbitrary key-value data. Returned as-is in webhooks. | Datos clave-valor arbitrarios. Se devuelven tal cual en los webhooks. |
Response 201 Created
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"address": "TXyz1234567890abcdef",
"payment_url": null,
"qr_code": "data:image/png;base64,...",
"network": "TRC20",
"currency": "USDT",
"memo": "",
"amount_usd": null,
"tx_hash": "",
"external_user_id": "user_42",
"external_reference": "",
"expires_at": "2026-07-10T19:00:00Z",
"metadata": {},
"created_at": "2026-07-08T19:00:00Z"
}
List Deposits Listar Depósitos
Query parameters
Parámetros de consulta
| Param | Parámetro | Description | Descripción |
|---|---|---|---|
| external_user_id | Filter by user identifier. | Filtrar por identificador de usuario. | |
| status | Filter by status: pending, paying, confirmed, expired. |
Filtrar por estado: pending, paying, confirmed, expired. |
Get Deposit Obtener Depósito
Verify Deposit Verificar Depósito
confirmed or expired, the provider is not queried again.
confirmed o expired, no se consulta al proveedor nuevamente.
Auto Sweep (External Cron) Auto Sweep (Cron Externo)
Channel 1 — owner sweep. Withdraws balance − reserved − fee_buffer to the Provider Account's payout_address. Does not pay affiliates.
Only runs for Provider Accounts with auto_payout_enabled=true.
Canal 1 — sweep del dueño. Retira balance − reserved − fee_buffer hacia payout_address de la Provider Account. No paga afiliados.
Solo ejecuta si la Provider Account tiene auto_payout_enabled=true.
Headers
Headers
| Header | Description | Descripción |
|---|---|---|
| X-Cron-Secret | Required. Must match CRON_SECRET. |
Requerido. Debe coincidir con CRON_SECRET. |
Optional JSON body
Body JSON opcional
{ "reserved": 0, "provider_account_id": null }
Example response
Respuesta de ejemplo
{
"processed": 1,
"results": [{
"account": "My OxaPay",
"account_id": "7e6f2ca0-...",
"ok": true,
"balance": 500.0,
"reserved": 125.5,
"amount_sent": 373.5,
"currency": "USDT",
"withdrawal_id": "...",
"track_id": "12345",
"status": "submitted"
}]
}
Affiliate Withdrawal Retiro de Afiliado
Channel 2 — affiliate payout. Your store requests a specific amount to an affiliate wallet. Requires store API key. Independent of auto_payout_enabled.
Canal 2 — pago a afiliado. Tu tienda pide un monto concreto a la wallet del afiliado. Requiere Api-Key. Independiente de auto_payout_enabled.
{
"amount": 50,
"address": "T...",
"currency": "USDT",
"network": "TRC20",
"note": "affiliate #123",
"external_ref": "aff_123"
}
Also: GET /api/v1/withdrawals/affiliate/ and GET /api/v1/withdrawals/affiliate/{id}/
También: GET /api/v1/withdrawals/affiliate/ y GET /api/v1/withdrawals/affiliate/{id}/
Reserved Balance URL (for auto-sweep) URL de Reserved Balance (para auto-sweep)
Before sweeping, Cryptopaid calls each linked store's reserved_balance_url (if set) to know how much to hold back (affiliates, etc.). Signed with webhook_secret.
Antes del sweep, Cryptopaid consulta reserved_balance_url de cada tienda vinculada para saber cuánto retener (afiliados, etc.). Firmado con webhook_secret.
GET {reserved_balance_url}
X-Cryptopaid-Signature: sha256=...
X-Cryptopaid-Timestamp: 1720000000
Response:
{
"currency": "USDT",
"affiliates_pending": 125.5,
"other_reserved": 0,
"as_of": "2026-07-15T03:00:00Z"
}
reserved_balance_url configured and the request fails, the sweep for that account is skipped (fail-closed).reserved_balance_url y la petición falla, el sweep de esa cuenta se omite (fail-closed).Receiving Webhooks Recibir Webhooks
When a deposit is confirmed, Cryptopaid sends a POST request to your store's webhook_url with the following JSON payload:
Cuando se confirma un depósito, Cryptopaid envía una solicitud POST al webhook_url de tu tienda con el siguiente payload JSON:
{
"event": "deposit.confirmed",
"deposit_id": "550e8400-e29b-41d4-a716-446655440000",
"external_user_id": "user_42",
"external_reference": "",
"amount_usd": "100.00",
"tx_hash": "abc123...",
"network": "TRC20",
"currency": "USDT",
"metadata": {}
}
Your endpoint must return a 2xx HTTP status. If it fails, Cryptopaid will retry up to 5 times with exponential backoff (30s → 2m → 10m → 30m → 1h).
Tu endpoint debe devolver un estado HTTP 2xx. Si falla, Cryptopaid reintentará hasta 5 veces con backoff exponencial (30s → 2m → 10m → 30m → 1h).
Verifying HMAC Signature Verificar Firma HMAC
Every webhook includes a X-Cryptopaid-Signature: sha256=<hex> header. Verify it using your store's webhook_secret before processing the payload.
Cada webhook incluye un header X-Cryptopaid-Signature: sha256=<hex>. Verifícalo usando el webhook_secret de tu tienda antes de procesar el payload.
import hashlib, hmac
def verify_signature(raw_body: bytes, header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
received = header.removeprefix("sha256=")
return hmac.compare_digest(expected, received)
# Django / Flask example# Ejemplo Django / Flask
raw_body = request.body # raw bytes, NOT parsed JSON# bytes crudos, NO JSON parseado
sig_header = request.headers.get("X-Cryptopaid-Signature", "")
if not verify_signature(raw_body, sig_header, WEBHOOK_SECRET):
return HttpResponse(status=401)
data = json.loads(raw_body)
# Process data["amount_usd"], data["external_user_id"], etc.# Procesa data["amount_usd"], data["external_user_id"], etc.
Status Values Estados
| Status | Description | Descripción |
|---|---|---|
| pending | Address generated, waiting for the user to send crypto. | Dirección generada, esperando que el usuario envíe crypto. |
| paying | Transaction detected on-chain but not yet confirmed. | Transacción detectada on-chain pero aún no confirmada. |
| confirmed | Payment fully confirmed. amount_usd is now set. |
Pago completamente confirmado. amount_usd ya tiene valor. |
| expired | Address was revoked after the configured expiration period. | La dirección fue revocada tras el período de expiración configurado. |
Error Codes Códigos de Error
| HTTP Status | Estado HTTP | Meaning | Significado |
|---|---|---|---|
| 400 | Invalid request body or provider error. | Cuerpo de solicitud inválido o error del proveedor. | |
| 401 | Missing or invalid API key. | API key faltante o inválida. | |
| 404 | Deposit not found (or belongs to another store). | Depósito no encontrado (o pertenece a otra tienda). | |
| 410 | Deposit has expired — create a new one. | El depósito ha expirado — crea uno nuevo. | |
| 503 | Store has no active provider account. | La tienda no tiene provider account activa. |
Provider Variables — OxaPay Variables del Proveedor — OxaPay
Credentials and liquidity on Provider Account. Deposit settings are fields on Store.
Credenciales y liquidez en Provider Account. Depósitos en campos de Store.
Provider Account — Credentials
Provider Account — Credenciales
| Variable | Variable | Sensitive | Sensible | Description | Descripción |
|---|---|---|---|---|---|
| merchant_key | 🔒 | Main API key for creating deposits and static addresses. | Clave API principal para crear depósitos y direcciones estáticas. | ||
| payout_key | 🔒 | Key with payout permissions. Required for automatic withdrawals. | Clave con permisos de payout. Requerida para retiros automáticos. | ||
| general_key | 🔒 | General key used to query account balance. | Clave general para consultar el balance de la cuenta. |
Provider Account — Liquidity / sweep settings
Provider Account — Liquidez / auto-sweep
| Variable | Variable | Type | Tipo | Default | Default | Description | Descripción |
|---|---|---|---|---|---|---|---|
| auto_convert_to | string |
USDT |
Target currency for conversion. (Store) | Moneda destino. (Store) | |||
| reuse_open_deposit | boolean |
true |
Reuses open deposit address. (Store) | Reutiliza dirección abierta. (Store) | |||
| revoke_after_hours | integer |
48 |
Hours before address is revoked. (Store) | Horas antes de revocar. (Store) | |||
| auto_payout_enabled | boolean |
false |
Enables auto-sweep cron for this Provider Account. (Provider Account) | Activa auto-sweep en cron. (Provider Account) | |||
| payout_address | string |
— | Owner wallet for auto-sweep (not affiliates). (Provider Account) | Wallet del dueño para auto-sweep. (Provider Account) | |||
| payout_currency | string |
USDT |
Currency for balance/payout. (Provider Account) | Moneda de balance/retiro. (Provider Account) | |||
| payout_network | string |
— | Network for payouts. (Provider Account) | Red de retiros. (Provider Account) | |||
| payout_fee_reserve | float |
1.0 |
Fee buffer kept in account. (Provider Account) | Buffer de comisión. (Provider Account) | |||
| min_payout_amount | float |
1 |
Minimum sweep amount. (Provider Account) | Monto mínimo de sweep. (Provider Account) |
Admin Guide Guía de Admin
Creating a Provider Account
Crear una Provider Account
- Go to Admin → Provider Accounts → Add.
- Set
name,slug,provider_slug=oxapay. - Fill credentials:
merchant_key,general_key,payout_key. - Set
payout_addressand enableauto_payout_enabledonly when ready for auto-sweep.
- Ve a Admin → Provider Accounts → Añadir.
- Configura
name,slug,provider_slug=oxapay. - Completa credenciales:
merchant_key,general_key,payout_key. - Configura
payout_addressy activaauto_payout_enabledsolo cuando quieras auto-sweep.
Creating a Store
Crear una Tienda
- Go to Admin → Stores → Add Store.
- Link
provider_account, setwebhook_url,webhook_secret, optionalreserved_balance_url. - Save — copy the API key from the success message.
- Set deposit fields and webhooks on the Store.
- Ve a Admin → Stores → Añadir Store.
- Vincula
provider_account, configura webhooks y opcionalreserved_balance_url. - Guarda — copia la API key del mensaje de éxito.
- Configura depósitos y webhooks en la Store.
Adding a New Payment Provider
Añadir un Nuevo Proveedor de Pagos
- Create
apps/providers/<slug>/adapter.pyimplementingBasePaymentProvider. - Register it in
apps/providers/apps.py→registry.register("slug", MyProvider). - Create a Provider Account with
provider_slug = <slug>in Admin. - No changes needed in your client projects.
- Crea
apps/providers/<slug>/adapter.pyimplementandoBasePaymentProvider. - Regístralo en
apps/providers/apps.py→registry.register("slug", MyProvider). - Crea una Provider Account con
provider_slug = <slug>en Admin. - No se necesitan cambios en tus proyectos cliente.