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?

💸
Remesas
El beneficiario recibe en su wallet en segundos tras la liquidación on-chain, sin necesitar cuenta bancaria.
💳
Emisión de tarjetas
Tarjetas virtuales Visa vinculadas a wallets. Construido sobre el programa ya operativo con Kripicard.
🏦
Custody-as-a-Service
Infraestructura cripto completa vía API. Sin construir nodos, sin gestionar claves. BSC, Polygon y Bitcoin.
🔐
Custodia Multi-chain
Wallets en BSC, Polygon y Bitcoin con segregación Hot/Treasury/Master. Seguridad institucional.
📡
Webhooks en tiempo real
Notificaciones de depósitos, retiros, conversiones y más. Sin polling, con firma HMAC.
📦
SDKs en 6 lenguajes
JavaScript, Python, PHP, Java, Go y C#. Sin dependencias, firma HMAC automática.

Cómo empezar

⚡ Nuevo: prueba la API directamente desde el navegador con el API Explorer — sin escribir ni una línea de código. Firma HMAC automática server-side.
  1. Crea tu cuenta empresarialcompleta el formulario, verifica tu correo y nuestro equipo inicia el proceso KYB de tu empresa.
  2. Recibe tus credenciales de sandbox — tras la aprobación, tu cuenta sandbox se activa automáticamente con un par api_key / hmac_secret.
  3. Da de alta a tus usuarios — cada usuario de tu sistema se registra con su propio external_user_id (un identificador que tú defines).
  4. Crea wallets y opera — wallets on-chain en BSC, Polygon o BTC; retiros, transferencias y conversiones desde el mismo API.
  5. Configura webhooks — recibe notificaciones en tiempo real de depósitos, retiros, conversiones y más, sin hacer polling.

Ambientes

AmbienteDescripciónCredenciales
sandboxTestnet real (BSC Amoy, Polygon Amoy, BTC testnet). Fondos sin valor real.Emitidas automáticamente al aprobar el KYB.
productionMainnet 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

RecursoFormatoDescarga
Especificación OpenAPI 3.0openapi.yaml↓ YAML
Colección Postmanpostman-collection.json↓ JSON
Guía de integraciónMarkdown↓ MD
Checklist de seguridadMarkdown↓ 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.

LenguajePaqueteInstalaciónEstado
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
PHPbitalcer/partner-apicomposer require bitalcer/partner-api⬇ Descarga directa
Javacom.bitalcer:partner-apiimplementation com.bitalcer:partner-api:1.0.0⬇ Descarga directa
Gogithub.com/bitalcer/partner-api-gogo get github.com/bitalcer/partner-api-go⬇ Descarga directa
C# (.NET)Bitalcer.PartnerApidotnet 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

HeaderValor
x-api-keyTu API key en texto plano. Identifica tu cuenta y el ambiente (sandbox/production).
x-timestampEpoch en milisegundos como string (ej. "1782832426118"). Debe estar dentro de ±5 minutos del reloj del servidor.
x-signatureHMAC-SHA256("{timestamp}:{raw_body}", hmac_secret) en hexadecimal. Para requests GET (sin body), raw_body es un string vacío.
⚠️ Importante: firma siempre el body exacto que vas a enviar, no un objeto re-serializado. Si tu cliente reordena las claves JSON o cambia los espacios, la firma no coincidirá con lo que recibe el servidor.

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ódigoSignificadoCausas típicas
200OKRequest exitoso.
201CreatedRecurso creado (usuario, wallet, orden, retiro).
400Bad RequestParámetro faltante o formato inválido (invalid_request).
401Unauthorizedmissing_auth_headers, unauthorized (api_key no encontrada o suspendida), invalid_signature.
402Payment RequiredINSUFFICIENT_PARTNER_TREASURY — el saldo prepagado de tu empresa no alcanza para cubrir la operación.
404Not Foundpartner_user_not_found (llamaste a wallets/transacciones sin haber creado primero el usuario con POST /partner/v1/users).
409ConflictEstado inválido de la orden (invalid_state), cotización vencida (quote_expired), inventario insuficiente.
422UnprocessableRegla de negocio — saldo insuficiente del usuario (insufficient_funds), wallet inexistente, etc.
429Too Many RequestsRate 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.
501Not ImplementedCHAIN_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

EventoCuándo se dispara
wallet.createdCuando se crea una wallet para un usuario tuyo.
deposit.confirmedCuando se confirma un depósito on-chain (BSC/Polygon/BTC) en la wallet de un usuario tuyo.
withdraw.completedCuando un retiro a dirección externa se ejecuta exitosamente.
transfer.completedCuando una transferencia interna entre dos usuarios tuyos se completa.
conversion.executedCuando 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:

IntentoEspera antes del siguiente intento
1 → 21 minuto
2 → 35 minutos
3 → 430 minutos
4 → 52 horas
5 → 612 horas
Tras 6 intentos fallidosEstado 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.

POST /partner/v1/users

Este 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ódigoError
400invalid_requestexternal_user_id vacío.

Wallets

POST /partner/v1/wallets

Crea 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 retorna 404 partner_user_not_found.
GET /partner/v1/wallets/{external_user_id}/balance

Consulta el saldo de un token.

Query params

ParamDefault
tokenUSDT
chainbsc
GET /partner/v1/wallets/{external_user_id}/address

Devuelve la dirección de depósito. Si el usuario no tiene wallet en esa cadena, la crea al momento.

Query params

ParamDefault
chainbsc

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.

BTC: los retiros on-chain en BTC para partners no están disponibles aún (501 CHAIN_NOT_YET_SUPPORTED). Usa BSC o Polygon para retiros de tokens estables.
POST /partner/v1/transactions/withdraw

Retira 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ódigoErrorCausa
402INSUFFICIENT_PARTNER_TREASURYTu saldo prepagado no cubre el monto.
429DAILY_VOLUME_LIMIT_EXCEEDEDLímite diario de volumen del partner.
501CHAIN_NOT_YET_SUPPORTEDBTC para partners no disponible aún.
POST /partner/v1/transactions/transfer

Transferencia 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.
GET /partner/v1/treasury/balance

Respuesta 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

  1. Quote — previsualiza el precio y el monto resultante (sin escritura en base de datos).
  2. Create order — crea la orden en estado quoted y obtén el order_id.
  3. Execute — ejecuta la conversión con ese order_id. La cotización vence si no ejecutas a tiempo.
  4. Status — consulta el estado de la orden en cualquier momento.
GET /partner/v1/conversion/quote

Query 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
}
POST /partner/v1/conversion/orders

Body

{
  "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" }
POST /partner/v1/conversion/execute
{ "external_user_id": "cust-00321", "order_id": "uuid-..." }
GET /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.

⏱ ~15 minutos para completar este quickstart. Necesitas tus credenciales de sandbox (api_key + hmac_secret). Si aún no las tienes, crea tu cuenta.

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")
⚠️ En producción: la conversión y la transferencia descuentan del Partner Treasury (tu saldo prepagado en USD). Asegúrate de tener fondeo suficiente antes de operar a escala. Si el saldo no alcanza, la API responde 402 INSUFFICIENT_PARTNER_TREASURY.

Resumen del flujo

#EndpointQué hace
1POST /partner/v1/usersRegistra remitente
2POST /partner/v1/usersRegistra beneficiario
3POST /partner/v1/walletsCrea wallets BSC para ambos
4GET /quote → POST /orders → POST /executeConvierte GTQ a USDT
5POST /partner/v1/transactions/transferTransfiere 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.

⏱ ~20 minutos para completar la integración. Requiere credenciales de sandbox. Contacta a tu ejecutivo de cuenta para habilitar el módulo Cards API en tu workspace.

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:

EventoCuándo se dispara
wallet.createdAl crear la wallet del titular.
deposit.confirmedAl confirmarse un depósito on-chain en la wallet.
conversion.executedAl ejecutarse una conversión GTQ→USDT.
withdraw.completedAl liquidarse un pago con tarjeta (retiro contra la wallet).
⚠️ En producción: la emisión de tarjetas requiere que el módulo Cards API esté activo en tu workspace (gestionable desde el Marketplace del dashboard). Contacta a [email protected] para activarlo.

Resumen del flujo

#EndpointQué hace
1POST /partner/v1/usersRegistra al titular
2POST /partner/v1/walletsCrea wallet del titular
3conversion/quote → orders → executeConvierte GTQ a USDT
4GET /wallets/{id}/balanceVerifica saldo disponible
5GET /wallets/{id}/addressObtén dirección para Kripicard
6WebhooksRecibe 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.

👛
Wallets on-chain
Crea wallets para tus usuarios en BSC, Polygon y Bitcoin con una llamada a la API. Sin tocar un nodo.
🔐
Custodia segregada
Arquitectura Hot/Treasury/Master ya operando. Tus usuarios nunca están expuestos al riesgo de una sola wallet.
💱
Conversión GTQ ↔ USDT
On/off-ramp integrado. Tus usuarios convierten Quetzales a dólares digitales y viceversa sin exchange.
📡
Webhooks en tiempo real
Notificaciones de depósitos, retiros y conversiones. Sin polling, con firma HMAC.
⏱ ~15 minutos para tener el sistema completo funcionando. Necesitas tus credenciales de sandbox. Si aún no las tienes, crea tu cuenta.

¿Qué incluye este quickstart?

En 15 minutos tendrás operando el stack completo que a una fintech le tomaría meses construir:

  1. Registro de usuarios — cada usuario de tu sistema obtiene una identidad en Bitalcer vía POST /partner/v1/users.
  2. Wallets on-chain — direcciones de depósito en BSC, Polygon o Bitcoin generadas por la API. Sin tocar un nodo.
  3. Conversión GTQ ↔ USDT — tus usuarios entran y salen del ecosistema cripto. Flujo quote → order → execute.
  4. Retiros on-chain — tus usuarios pueden enviar sus fondos a cualquier dirección externa.
  5. 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.

⚠️ En producción:
  • 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

#EndpointQué hace
1POST /partner/v1/usersRegistra al usuario
2POST /partner/v1/walletsCrea wallet del usuario
3GET /conversion/quoteCotiza GTQ↔USDT
4POST /conversion/ordersCrea orden de conversión
5POST /conversion/executeEjecuta la conversión
6POST /transactions/withdrawRetira a dirección externa (off-ramp)
7WebhooksRecibe 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.

Cargando…

Changelog

Versiones publicadas del API y avisos de deprecación.

Cargando…

Estado del sistema

Estado operativo en tiempo real por componente del API. Actualizado cada 5 minutos.

Estado general:


ComponenteEstadoLatencia p95Error rateActualizado
Cargando…
En esta página