Introducción
La Bitalcer Custody-as-a-Service Partner API te permite integrar custodia cripto multi-chain, conversión de Quetzales a dólares digitales y pagos directamente en tu producto, sin construir la infraestructura desde cero.
¿Qué puedes hacer con la API?
Cómo empezar
- Crea tu cuenta empresarial — completa el formulario, verifica tu correo y nuestro equipo inicia el proceso KYB de tu empresa.
- Recibe tus credenciales de sandbox — tras la aprobación, tu cuenta sandbox se activa automáticamente con un par
api_key/hmac_secret. - Da de alta a tus usuarios — cada usuario de tu sistema se registra con su propio
external_user_id(un identificador que tú defines). - Crea wallets y opera — wallets on-chain en BSC, Polygon o BTC; retiros, transferencias y conversiones desde el mismo API.
- Configura webhooks — recibe notificaciones en tiempo real de depósitos, retiros, conversiones y más, sin hacer polling.
Ambientes
| Ambiente | Descripción | Credenciales |
|---|---|---|
sandbox | Testnet real (BSC Amoy, Polygon Amoy, BTC testnet). Fondos sin valor real. | Emitidas automáticamente al aprobar el KYB. |
production | Mainnet real (BSC, Polygon, BTC). Mueve fondos reales. | Emitidas manualmente tras completar la revisión de producción. |
URL base
https://api.bitalcer.com
Todos los endpoints del API están bajo esta URL. El ambiente (sandbox/production) lo determinan las credenciales, no la URL.
Recursos descargables
| Recurso | Formato | Descarga |
|---|---|---|
| Especificación OpenAPI 3.0 | openapi.yaml | ↓ YAML |
| Colección Postman | postman-collection.json | ↓ JSON |
| Guía de integración | Markdown | ↓ MD |
| Checklist de seguridad | Markdown | ↓ MD |
La colección Postman incluye firma HMAC automática vía pre-request script. Solo configura las variables api_key y hmac_secret de la colección y todos los requests se firman solos.
📦 SDKs oficiales
Integra la Partner API en minutos con nuestros SDKs — sin dependencias, firma HMAC automática, menos de 15 KB cada uno. JavaScript y Python ya publicados en sus registries oficiales.
| Lenguaje | Paquete | Instalación | Estado |
|---|---|---|---|
| JavaScript | @bitalcer/partner-api |
npm install @bitalcer/partner-api |
Publicado v1.0.0 |
| Python | bitalcer-partner-api |
pip install bitalcer-partner-api |
Publicado v1.0.0 |
| PHP | bitalcer/partner-api | composer require bitalcer/partner-api | ⬇ Descarga directa |
| Java | com.bitalcer:partner-api | implementation com.bitalcer:partner-api:1.0.0 | ⬇ Descarga directa |
| Go | github.com/bitalcer/partner-api-go | go get github.com/bitalcer/partner-api-go | ⬇ Descarga directa |
| C# (.NET) | Bitalcer.PartnerApi | dotnet add package Bitalcer.PartnerApi | ⬇ Descarga directa |
Código fuente de los 6 SDKs en /frontend/assets/sdk/. Versiones completas y changelog en 📦 SDKs oficiales. ¿Prefieres no instalar nada? Usa el ⚡ API Explorer.
Autenticación
Cada request a /partner/v1/* usa autenticación HMAC-SHA256 con tres headers. No hay sesiones, no hay JWT — cada llamada es autocontenida y verificable de forma independiente.
Los tres headers requeridos
| Header | Valor |
|---|---|
x-api-key | Tu API key en texto plano. Identifica tu cuenta y el ambiente (sandbox/production). |
x-timestamp | Epoch en milisegundos como string (ej. "1782832426118"). Debe estar dentro de ±5 minutos del reloj del servidor. |
x-signature | HMAC-SHA256("{timestamp}:{raw_body}", hmac_secret) en hexadecimal. Para requests GET (sin body), raw_body es un string vacío. |
Ejemplos de firma
Python
import hmac, hashlib, time, requests, json
API_KEY = "bak_..."
HMAC_SECRET = "..."
def call(method, path, body=None):
payload = json.dumps(body, separators=(',', ':')) if body else ""
ts = str(round(time.time() * 1000))
sig = hmac.new(HMAC_SECRET.encode(), f"{ts}:{payload}".encode(), hashlib.sha256).hexdigest()
headers = {"x-api-key": API_KEY, "x-timestamp": ts, "x-signature": sig}
if body:
headers["Content-Type"] = "application/json"
return requests.request(method, f"https://api.bitalcer.com{path}", headers=headers, data=payload)
res = call("GET", "/partner/v1/ping")
print(res.json()) # {"status": "ok", ...}
JavaScript (Node.js)
const crypto = require('crypto');
const fetch = require('node-fetch');
const API_KEY = "bak_...";
const HMAC_SECRET = "...";
async function call(method, path, body = null) {
const payload = body ? JSON.stringify(body) : "";
const ts = String(Date.now());
const sig = crypto.createHmac('sha256', HMAC_SECRET)
.update(`${ts}:${payload}`).digest('hex');
const headers = { 'x-api-key': API_KEY, 'x-timestamp': ts, 'x-signature': sig };
if (body) headers['Content-Type'] = 'application/json';
const res = await fetch(`https://api.bitalcer.com${path}`, { method, headers, body: payload || undefined });
return res.json();
}
call("GET", "/partner/v1/ping").then(console.log);
PHP
function callApi($method, $path, $apiKey, $secret, $body = null) {
$payload = $body ? json_encode($body, JSON_UNESCAPED_SLASHES) : '';
$ts = (string) round(microtime(true) * 1000);
$sig = hash_hmac('sha256', "{$ts}:{$payload}", $secret);
$headers = ["x-api-key: $apiKey", "x-timestamp: $ts", "x-signature: $sig"];
if ($body) $headers[] = 'Content-Type: application/json';
$ch = curl_init("https://api.bitalcer.com{$path}");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $payload ?: null,
CURLOPT_RETURNTRANSFER => true,
]);
return json_decode(curl_exec($ch), true);
}
Protección anti-replay
El header x-timestamp debe estar dentro de ±5 minutos (300 000 ms) del reloj del servidor. Si tu servidor no está sincronizado con NTP y envías un timestamp viejo, la llamada será rechazada con 401 invalid_signature aunque la firma sea matemáticamente correcta.
Errores
Todas las respuestas de error incluyen un campo error con un código estable pensado para manejo programático — no para mostrar directamente al usuario final.
{ "error": "partner_user_not_found" }
Códigos HTTP
| Código | Significado | Causas típicas |
|---|---|---|
200 | OK | Request exitoso. |
201 | Created | Recurso creado (usuario, wallet, orden, retiro). |
400 | Bad Request | Parámetro faltante o formato inválido (invalid_request). |
401 | Unauthorized | missing_auth_headers, unauthorized (api_key no encontrada o suspendida), invalid_signature. |
402 | Payment Required | INSUFFICIENT_PARTNER_TREASURY — el saldo prepagado de tu empresa no alcanza para cubrir la operación. |
404 | Not Found | partner_user_not_found (llamaste a wallets/transacciones sin haber creado primero el usuario con POST /partner/v1/users). |
409 | Conflict | Estado inválido de la orden (invalid_state), cotización vencida (quote_expired), inventario insuficiente. |
422 | Unprocessable | Regla de negocio — saldo insuficiente del usuario (insufficient_funds), wallet inexistente, etc. |
429 | Too Many Requests | Rate limit excedido (too_many_requests) o límites de volumen diario/mensual del partner (DAILY_VOLUME_LIMIT_EXCEEDED). El header Retry-After indica cuántos segundos esperar. |
501 | Not Implemented | CHAIN_NOT_YET_SUPPORTED — la cadena solicitada (ej. BTC para retiros) aún no está disponible para partners. |
Reintento con backoff
Para errores 429, usa el valor del header Retry-After. Para errores 5xx transitorios, implementa backoff exponencial comenzando en 1 segundo y no más de 3 reintentos. Para errores 4xx (excepto 429), no reintentes — son errores de lógica que no se resuelven solos.
Webhooks
Los webhooks notifican a tu servidor en tiempo real de eventos relevantes, sin necesidad de hacer polling. Bitalcer firma cada entrega con el mismo esquema HMAC que usas para autenticar tus requests salientes — solo que con un secreto diferente (el webhook_secret, distinto de tu hmac_secret).
Eventos disponibles
| Evento | Cuándo se dispara |
|---|---|
wallet.created | Cuando se crea una wallet para un usuario tuyo. |
deposit.confirmed | Cuando se confirma un depósito on-chain (BSC/Polygon/BTC) en la wallet de un usuario tuyo. |
withdraw.completed | Cuando un retiro a dirección externa se ejecuta exitosamente. |
transfer.completed | Cuando una transferencia interna entre dos usuarios tuyos se completa. |
conversion.executed | Cuando una orden de conversión Q↔USDT se ejecuta exitosamente. |
Estructura del payload
{
"event_type": "deposit.confirmed",
"event_id": 42,
"data": {
"chain": "bsc",
"amount": "100.00",
"token": "USDT",
"tx_hash": "0xabc123..."
}
}
Verificar la firma entrante
Cada entrega incluye los headers x-timestamp y x-signature. Verifica siempre la firma antes de procesar el payload:
// Python
import hmac, hashlib
def verify_webhook(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), f"{timestamp}:{raw_body.decode()}".encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
Política de reintentos
Si tu endpoint no responde 2xx, Bitalcer reintenta con backoff exponencial:
| Intento | Espera antes del siguiente intento |
|---|---|
| 1 → 2 | 1 minuto |
| 2 → 3 | 5 minutos |
| 3 → 4 | 30 minutos |
| 4 → 5 | 2 horas |
| 5 → 6 | 12 horas |
| Tras 6 intentos fallidos | Estado failed permanente. Recuperable con retry manual desde el dashboard de tu empresa. |
Configurar la URL de destino
Desde el dashboard de tu empresa → pestaña Organización → sección Organización → "Configurar webhook". El webhook_secret se muestra una sola vez al configurar — guárdalo igual que tu hmac_secret.
Usuarios
Antes de crear wallets, retiros o conversiones para un usuario, debes registrarlo con su external_user_id — el identificador que tú asignas dentro de tu propio sistema. Usa un UUID o un ID de tu base de datos; nunca PII directa.
/partner/v1/usersEste endpoint es idempotente: si el external_user_id ya existe para tu cuenta, devuelve el registro existente en vez de crear un duplicado. Puedes llamarlo de forma segura al inicio de cada sesión sin riesgo de duplicación.
Body
{
"external_user_id": "cust-00321" // string, obligatorio
}
Respuesta 201
{
"id": 45,
"partner_id": 7,
"external_user_id": "cust-00321",
"internal_user_id": null, // null hasta que se crea la primera wallet
"status": "active"
}
Errores
| Código | Error |
|---|---|
400 | invalid_request — external_user_id vacío. |
Wallets
/partner/v1/walletsCrea una wallet on-chain para un usuario ya registrado. Soporta BSC, Polygon y BTC.
Body
{ "external_user_id": "cust-00321", "chain": "bsc" }
// chain: "bsc" | "polygon" | "btc" | "bitcoin" (default: "bsc")
Respuesta 201
{ "external_user_id": "cust-00321", "address": "0x4b934FAa...", "chain": "bsc" }
Notas
- Se dispara el webhook
wallet.created. - El usuario debe haberse registrado antes con
POST /partner/v1/users; de lo contrario retorna404 partner_user_not_found.
/partner/v1/wallets/{external_user_id}/balanceConsulta el saldo de un token.
Query params
| Param | Default |
|---|---|
token | USDT |
chain | bsc |
/partner/v1/wallets/{external_user_id}/addressDevuelve la dirección de depósito. Si el usuario no tiene wallet en esa cadena, la crea al momento.
Query params
| Param | Default |
|---|---|
chain | bsc |
Transacciones
Retiros y transferencias se descuentan del Partner Treasury (tu saldo prepagado en USD), no del balance individual del usuario. Asegúrate de tener fondeo suficiente antes de operar a escala.
501 CHAIN_NOT_YET_SUPPORTED). Usa BSC o Polygon para retiros de tokens estables.
/partner/v1/transactions/withdrawRetira fondos de un usuario hacia una dirección externa.
Body
{
"external_user_id": "cust-00321",
"to_address": "0x9f2c...e31a",
"amount": "100.00",
"token": "USDT",
"chain": "bsc" // opcional, default "bsc"
}
Errores específicos
| Código | Error | Causa |
|---|---|---|
402 | INSUFFICIENT_PARTNER_TREASURY | Tu saldo prepagado no cubre el monto. |
429 | DAILY_VOLUME_LIMIT_EXCEEDED | Límite diario de volumen del partner. |
501 | CHAIN_NOT_YET_SUPPORTED | BTC para partners no disponible aún. |
/partner/v1/transactions/transferTransferencia interna entre dos usuarios tuyos (no sale on-chain).
Body
{
"sender_external_user_id": "cust-00321",
"receiver_external_user_id": "cust-00322",
"amount": "25.00",
"token": "USDT"
}
Partner Treasury
El Partner Treasury es tu saldo prepagado en USD. Cada retiro o transferencia se descuenta de aquí antes de tocar la liquidez compartida de Bitalcer. Si el saldo llega a cero, las operaciones son rechazadas con 402.
Fondeo
Dos vías de fondeo, coordinadas con tu ejecutivo de cuenta:
- Wire transfer internacional — transferencia bancaria a la cuenta de Bitalcer.
- On-chain — depósito de USDT vía BSC o Polygon a la wallet madre de Bitalcer.
/partner/v1/treasury/balanceRespuesta 200
{
"partner_id": 7,
"available_balance_usd": 4250.00,
"reserved_balance_usd": 0,
"tier": "standard"
}
Conversión
Convierte Quetzales (GTQ) a dólares digitales (USDT/USDC) y viceversa dentro del balance de un usuario. La conversión no consume Partner Treasury — mueve el propio saldo del usuario entre activos.
Flujo de 4 pasos
- Quote — previsualiza el precio y el monto resultante (sin escritura en base de datos).
- Create order — crea la orden en estado
quotedy obtén elorder_id. - Execute — ejecuta la conversión con ese
order_id. La cotización vence si no ejecutas a tiempo. - Status — consulta el estado de la orden en cualquier momento.
/partner/v1/conversion/quoteQuery params
?external_user_id=cust-00321&base_asset=GTQ"e_asset=USDT&amount=750
Respuesta 200
{
"pair": "GTQUSDT", "requested_amount": 750,
"estimated_amount_out": 100.0, "price_applied": 7.5,
"fee_amount": 0, "fee_bps": 0
}
/partner/v1/conversion/ordersBody
{
"external_user_id": "cust-00321",
"base_asset": "GTQ", "quote_asset": "USDT",
"requested_amount": 750, "side": "buy"
}
Respuesta 201
{ "order_id": "uuid-...", "status": "quoted", "quote_expires_at": "2026-07-01 10:35:00" }
/partner/v1/conversion/execute{ "external_user_id": "cust-00321", "order_id": "uuid-..." }
/partner/v1/conversion/status?external_user_id=cust-00321&order_id=uuid-...
Quickstart: Remesas
Integración completa de un flujo de remesas con la Partner API: registra al remitente y al beneficiario, crea sus wallets, fondea, convierte de GTQ a USDT si aplica, y transfiere instantáneamente al beneficiario sin costo on-chain.
1. Configura tu cliente
La Partner API usa autenticación HMAC-SHA256. Cada request debe incluir 3 headers: x-api-key, x-timestamp (epoch en ms) y x-signature (HMAC del timestamp y el body).
import hmac, hashlib, time, requests, json
API_KEY = "bak_..." # tu api_key de sandbox
HMAC_SECRET = "..." # tu hmac_secret de sandbox
BASE = "https://api.bitalcer.com"
def call(method, path, body=None):
payload = json.dumps(body, separators=(',', ':')) if body else ""
ts = str(round(time.time() * 1000))
sig = hmac.new(HMAC_SECRET.encode(), f"{ts}:{payload}".encode(), hashlib.sha256).hexdigest()
h = {"x-api-key": API_KEY, "x-timestamp": ts, "x-signature": sig}
if body: h["Content-Type"] = "application/json"
return requests.request(method, f"{BASE}{path}", headers=h, data=payload)
También puedes importar la colección Postman que ya incluye la firma HMAC automática.
2. Registra al remitente
Cada usuario de tu sistema se identifica con un external_user_id que tú defines. Este endpoint es idempotente: llamarlo de nuevo con el mismo ID no crea duplicados.
call("POST", "/partner/v1/users", {"external_user_id": "remitente-01"})
# → 201 { "id": 45, "external_user_id": "remitente-01", "status": "active" }
3. Registra al beneficiario
call("POST", "/partner/v1/users", {"external_user_id": "beneficiario-01"})
# → 201 { "id": 46, "external_user_id": "beneficiario-01", "status": "active" }
4. Crea wallets para ambos
Ambos necesitan wallet en la misma cadena. Usa BSC o Polygon (USDT).
# Wallet del remitente
call("POST", "/partner/v1/wallets", {"external_user_id": "remitente-01", "chain": "bsc"})
# → 201 { "address": "0xREM...", "chain": "bsc" }
# Wallet del beneficiario
call("POST", "/partner/v1/wallets", {"external_user_id": "beneficiario-01", "chain": "bsc"})
5. Convierte GTQ → USDT (si el remitente pagó en Quetzales)
Si el remitente entregó Quetzales en tu punto de pago, conviértelos a USDT para transferir al beneficiario en dólares digitales.
# Cotizar: 750 GTQ a USDT
call("GET", "/partner/v1/conversion/quote?external_user_id=remitente-01&base_asset=GTQ"e_asset=USDT&amount=750")
# → 200 { "estimated_amount_out": 100.0, "price_applied": 7.5 }
# Crear orden
call("POST", "/partner/v1/conversion/orders", {
"external_user_id": "remitente-01",
"base_asset": "GTQ", "quote_asset": "USDT",
"requested_amount": 750, "side": "buy"
})
# → 201 { "order_id": "abc-123", "status": "quoted" }
# Ejecutar
call("POST", "/partner/v1/conversion/execute", {
"external_user_id": "remitente-01", "order_id": "abc-123"
})
# → 200 { "status": "executed" }
6. Transfiere al beneficiario
Transferencia interna instantánea entre tus usuarios. No sale on-chain — sin comisión de gas, sin tiempo de confirmación.
call("POST", "/partner/v1/transactions/transfer", {
"sender_external_user_id": "remitente-01",
"receiver_external_user_id": "beneficiario-01",
"amount": "100.00",
"token": "USDT"
})
# → 201 { "transfer_id": "tr-456", "status": "completed" }
7. Verifica los saldos
call("GET", "/partner/v1/wallets/remitente-01/balance?token=USDT")
call("GET", "/partner/v1/wallets/beneficiario-01/balance?token=USDT")
402 INSUFFICIENT_PARTNER_TREASURY.
Resumen del flujo
| # | Endpoint | Qué hace |
|---|---|---|
| 1 | POST /partner/v1/users | Registra remitente |
| 2 | POST /partner/v1/users | Registra beneficiario |
| 3 | POST /partner/v1/wallets | Crea wallets BSC para ambos |
| 4 | GET /quote → POST /orders → POST /execute | Convierte GTQ a USDT |
| 5 | POST /partner/v1/transactions/transfer | Transfiere USDT al beneficiario |
Quickstart: Emisión de tarjetas
Integra el programa de tarjetas virtuales de Bitalcer — construido sobre la misma base del programa Visa virtual ya operativo con Kripicard. Tus usuarios pueden tener una tarjeta virtual vinculada a su wallet para gastar su saldo cripto como si fuera moneda local.
1. Configura tu cliente HMAC
Igual que en el quickstart de Remesas. Importa la colección Postman o configura tu cliente HTTP con los 3 headers HMAC.
import hmac, hashlib, time, requests, json
API_KEY = "bak_..."
HMAC_SECRET = "..."
BASE = "https://api.bitalcer.com"
def call(method, path, body=None):
payload = json.dumps(body, separators=(',', ':')) if body else ""
ts = str(round(time.time() * 1000))
sig = hmac.new(HMAC_SECRET.encode(), f"{ts}:{payload}".encode(), hashlib.sha256).hexdigest()
h = {"x-api-key": API_KEY, "x-timestamp": ts, "x-signature": sig}
if body: h["Content-Type"] = "application/json"
return requests.request(method, f"{BASE}{path}", headers=h, data=payload)
2. Registra al titular de la tarjeta
call("POST", "/partner/v1/users", {"external_user_id": "titular-01"})
# → 201 { "id": 50, "external_user_id": "titular-01", "status": "active" }
3. Crea su wallet y fondea
La tarjeta se descuenta del saldo USDT de la wallet del usuario. Asegúrate de que tenga saldo suficiente antes de emitirla.
call("POST", "/partner/v1/wallets", {"external_user_id": "titular-01", "chain": "bsc"})
# → 201 { "address": "0xTIT..." }
4. Convierte GTQ → USDT si el usuario fondeó en Quetzales
# Quote
call("GET", "/partner/v1/conversion/quote?external_user_id=titular-01&base_asset=GTQ"e_asset=USDT&amount=1500")
# Create order + execute
call("POST", "/partner/v1/conversion/orders", {
"external_user_id": "titular-01",
"base_asset": "GTQ", "quote_asset": "USDT",
"requested_amount": 1500, "side": "buy"
})
call("POST", "/partner/v1/conversion/execute", {
"external_user_id": "titular-01",
"order_id": ""
})
5. Verifica el saldo disponible
call("GET", "/partner/v1/wallets/titular-01/balance?token=USDT")
# → 200 { "balance": "200.00000000", "token": "USDT", "chain": "bsc" }
6. Emite la tarjeta virtual
La emisión de tarjeta se gestiona a través de la integración con Kripicard. El endpoint expone los datos necesarios para solicitar la emisión:
# Obtén la dirección de la wallet para vincularla a la tarjeta
call("GET", "/partner/v1/wallets/titular-01/address?chain=bsc")
# → 200 { "address": "0xTIT...", "chain": "bsc" }
# Con el address + external_user_id, solicitas la emisión al módulo Cards
# (detalles específicos de la API de Kripicard según tu acuerdo de integración)
7. Recibe webhooks de eventos de tarjeta
Configura tu webhook URL desde el dashboard de tu empresa (Organización → Webhooks). Eventos relevantes para tarjetas:
| Evento | Cuándo se dispara |
|---|---|
wallet.created | Al crear la wallet del titular. |
deposit.confirmed | Al confirmarse un depósito on-chain en la wallet. |
conversion.executed | Al ejecutarse una conversión GTQ→USDT. |
withdraw.completed | Al liquidarse un pago con tarjeta (retiro contra la wallet). |
Resumen del flujo
| # | Endpoint | Qué hace |
|---|---|---|
| 1 | POST /partner/v1/users | Registra al titular |
| 2 | POST /partner/v1/wallets | Crea wallet del titular |
| 3 | conversion/quote → orders → execute | Convierte GTQ a USDT |
| 4 | GET /wallets/{id}/balance | Verifica saldo disponible |
| 5 | GET /wallets/{id}/address | Obtén dirección para Kripicard |
| 6 | Webhooks | Recibe notificaciones de eventos |
Custody-as-a-Service — Infraestructura cripto completa vía API
Este es el producto principal de Bitalcer: un sistema wallet custodial multi-chain ya construido y operando en producción que tu empresa integra vía API. No necesitas construir nodos, gestionar claves privadas, implementar firmas, ejecutar scanners de blockchain ni diseñar una arquitectura de custodia segregada — Bitalcer ya lo tiene corriendo en BSC, Polygon y Bitcoin.
¿Qué incluye este quickstart?
En 15 minutos tendrás operando el stack completo que a una fintech le tomaría meses construir:
- Registro de usuarios — cada usuario de tu sistema obtiene una identidad en Bitalcer vía
POST /partner/v1/users. - Wallets on-chain — direcciones de depósito en BSC, Polygon o Bitcoin generadas por la API. Sin tocar un nodo.
- Conversión GTQ ↔ USDT — tus usuarios entran y salen del ecosistema cripto. Flujo quote → order → execute.
- Retiros on-chain — tus usuarios pueden enviar sus fondos a cualquier dirección externa.
- Webhooks — notificaciones automáticas de cada evento. Tu sistema reacciona, no pregunta.
Todo esto corre sobre la misma infraestructura de custodia segregada (Hot/Treasury/Master) que Bitalcer ya opera en producción. Tu empresa no administra claves privadas, no corre nodos, no escribe smart contracts.
1. Configura tu cliente
import hmac, hashlib, time, requests, json
API_KEY = "bak_..."
HMAC_SECRET = "..."
BASE = "https://api.bitalcer.com"
def call(method, path, body=None):
payload = json.dumps(body, separators=(',', ':')) if body else ""
ts = str(round(time.time() * 1000))
sig = hmac.new(HMAC_SECRET.encode(), f"{ts}:{payload}".encode(), hashlib.sha256).hexdigest()
h = {"x-api-key": API_KEY, "x-timestamp": ts, "x-signature": sig}
if body: h["Content-Type"] = "application/json"
return requests.request(method, f"{BASE}{path}", headers=h, data=payload)
2. Registra al usuario y crea su wallet
call("POST", "/partner/v1/users", {"external_user_id": "usuario-01"})
call("POST", "/partner/v1/wallets", {"external_user_id": "usuario-01", "chain": "bsc"})
3. On-Ramp: GTQ → USDT
El usuario entrega Quetzales en tu punto de pago y recibe USDT en su wallet. El flujo de conversión en 4 pasos:
3a. Cotizar
call("GET", "/partner/v1/conversion/quote?external_user_id=usuario-01&base_asset=GTQ"e_asset=USDT&amount=750")
# → 200 {
# "pair": "GTQUSDT",
# "requested_amount": 750,
# "estimated_amount_out": 100.0,
# "price_applied": 7.5,
# "fee_amount": 0,
# "fee_bps": 0
# }
3b. Crear orden
call("POST", "/partner/v1/conversion/orders", {
"external_user_id": "usuario-01",
"base_asset": "GTQ", "quote_asset": "USDT",
"requested_amount": 750, "side": "buy"
})
# → 201 { "order_id": "abc-123", "status": "quoted", "quote_expires_at": "..." }
3c. Ejecutar la conversión
call("POST", "/partner/v1/conversion/execute", {
"external_user_id": "usuario-01", "order_id": "abc-123"
})
# → 200 { "order_id": "abc-123", "status": "executed" }
3d. Verificar saldo
call("GET", "/partner/v1/wallets/usuario-01/balance?token=USDT")
# → 200 { "balance": "100.00000000", "token": "USDT" }
4. Off-Ramp: USDT → GTQ
El usuario quiere retirar sus dólares digitales a Quetzales. Mismo flujo, dirección opuesta (side: "sell"):
# Cotizar: vender 100 USDT por GTQ
call("GET", "/partner/v1/conversion/quote?external_user_id=usuario-01&base_asset=USDT"e_asset=GTQ&amount=100")
# → 200 { "estimated_amount_out": 750.0, "price_applied": 7.5 }
# Crear orden
call("POST", "/partner/v1/conversion/orders", {
"external_user_id": "usuario-01",
"base_asset": "USDT", "quote_asset": "GTQ",
"requested_amount": 100, "side": "sell"
})
# → 201 { "order_id": "def-456", "status": "quoted" }
# Ejecutar
call("POST", "/partner/v1/conversion/execute", {
"external_user_id": "usuario-01", "order_id": "def-456"
})
# → 200 { "status": "executed" }
5. Retiro a dirección externa (si el usuario quiere sus fondos en otra wallet)
call("POST", "/partner/v1/transactions/withdraw", {
"external_user_id": "usuario-01",
"to_address": "0xUsuarioExterno...",
"amount": "50.00",
"token": "USDT",
"chain": "bsc"
})
# → 201 { "withdraw_id": "wd-789", "tx_hash": "0x...", "status": "pending" }
6. Recibe webhooks de confirmación
Suscríbete a los webhooks conversion.executed y withdraw.completed para notificar a tu usuario cuando la operación se complete, sin necesidad de polling.
- La conversión no consume Partner Treasury (mueve el saldo del usuario entre sus propios activos).
- El retiro (
withdraw) sí descuenta de tu Partner Treasury. - BTC para retiros no está disponible aún para partners (
501 CHAIN_NOT_YET_SUPPORTED). Usa BSC o Polygon.
Resumen del flujo
| # | Endpoint | Qué hace |
|---|---|---|
| 1 | POST /partner/v1/users | Registra al usuario |
| 2 | POST /partner/v1/wallets | Crea wallet del usuario |
| 3 | GET /conversion/quote | Cotiza GTQ↔USDT |
| 4 | POST /conversion/orders | Crea orden de conversión |
| 5 | POST /conversion/execute | Ejecuta la conversión |
| 6 | POST /transactions/withdraw | Retira a dirección externa (off-ramp) |
| 7 | Webhooks | Recibe confirmaciones en tiempo real |
SDKs oficiales
SDKs ligeros, sin dependencias externas, con firma HMAC-SHA256 automática. Generados desde la especificación OpenAPI de la Partner API. Cada SDK expone la misma API idiomática en su lenguaje.
Changelog
Versiones publicadas del API y avisos de deprecación.
Estado del sistema
Estado operativo en tiempo real por componente del API. Actualizado cada 5 minutos.
Estado general: —
| Componente | Estado | Latencia p95 | Error rate | Actualizado |
|---|---|---|---|---|
| Cargando… | ||||