# Guía de integración — Bitalcer Partner API

Esta guía cubre el camino completo: desde solicitar acceso hasta pasar a producción.
Para el detalle exacto de cada endpoint (parámetros, respuestas, códigos de error),
ver la especificación [`openapi.yaml`](./openapi.yaml).

## 1. Solicitar acceso (alta de empresa / KYB)

1. Desde la página institucional de Bitalcer, sección "Alianzas", completar el
   formulario de cuenta empresarial (correo corporativo, nombre legal, país,
   tipo de alianza buscada).
2. Verificar el correo y completar el expediente KYB: documentos legales de
   constitución, comprobante de domicilio fiscal, identificación del
   representante legal (verificación de identidad vía Didit) y un cuestionario
   AML básico (volumen estimado, países de operación, naturaleza del negocio).
3. El equipo de cumplimiento de Bitalcer revisa el expediente (dos niveles de
   aprobación). Al aprobarse, se crea automáticamente tu cuenta de partner en
   ambiente **sandbox** y se desbloquea el dashboard operativo.
4. Recibirás una invitación por correo para fijar la contraseña del primer
   usuario `owner` del dashboard de tu empresa.

## 2. Obtener credenciales de sandbox

1. Inicia sesión en el dashboard (`/partner/login.html`).
2. En la pestaña **Claves API** verás tu API key de sandbox (el campo
   `hmac_secret` solo se muestra **una vez**, al generarse — guárdalo de forma
   segura de inmediato; ver checklist de seguridad).
3. Sandbox opera sobre testnet real: BSC/Polygon Amoy y BTC testnet. Los fondos
   no tienen valor real — puedes probar libremente.

## 3. Autenticación de cada request

Cada llamada a `/partner/v1/*` requiere tres headers:

| Header | Contenido |
|---|---|
| `x-api-key` | Tu API key (texto plano) |
| `x-timestamp` | Epoch actual en **milisegundos**, como string |
| `x-signature` | `HMAC-SHA256("{x-timestamp}:{raw_body}", hmac_secret)` en hexadecimal |

Puntos críticos que causan rechazo (`401 invalid_signature`) si se ignoran:

- `raw_body` debe ser el **cuerpo exacto** que se envía en el request — para
  `GET` (sin body) es un string vacío `""`. Si tu cliente HTTP reserializa el
  JSON antes de firmar (por ejemplo, firmas un objeto y luego `json.dumps()`
  produce un string distinto al que realmente se envía), la firma no va a
  coincidir. Firma siempre el string final, no el objeto.
- `x-timestamp` debe estar dentro de **±5 minutos** del reloj de Bitalcer
  (protección anti-replay) — sincroniza el reloj del servidor que hace las
  llamadas (NTP).

Ejemplo (pseudo-código):

```
timestamp = str(round(time.time() * 1000))
body = json.dumps(payload, separators=(',', ':'))  # o "" si es GET
signature = hmac_sha256(secret, f"{timestamp}:{body}").hexdigest()

headers = {
    "x-api-key": API_KEY,
    "x-timestamp": timestamp,
    "x-signature": signature,
    "Content-Type": "application/json",
}
```

## 4. Flujo mínimo de integración

1. **`POST /partner/v1/users`** — da de alta a tu usuario final
   (`external_user_id` que tú defines). Idempotente: llamarlo de nuevo con el
   mismo id devuelve el registro existente.
2. **`POST /partner/v1/wallets`** — crea su wallet en la red que necesites
   (`bsc`, `polygon`, o `btc`). Devuelve la dirección de depósito.
3. El usuario recibe fondos en esa dirección (depósito on-chain real). Cuando
   se confirma, Bitalcer dispara el webhook `deposit.confirmed` (ver paso 6).
4. **`GET /partner/v1/wallets/{external_user_id}/balance`** — consulta su saldo
   en cualquier momento.
5. Para mover esos fondos:
   - **`POST /partner/v1/transactions/withdraw`** — retiro a una dirección
     externa (se descuenta de tu Partner Treasury prepagado, no del balance
     individual del usuario).
   - **`POST /partner/v1/transactions/transfer`** — transferencia interna
     entre dos usuarios tuyos.
   - Para convertir Q ↔ dólares digitales: `GET conversion/quote` (previsualizar)
     → `POST conversion/orders` (crear orden) → `POST conversion/execute`
     (ejecutar) → `GET conversion/status` (consultar).
6. **Configura tu `webhook_url`** desde el dashboard (pestaña que corresponda)
   para recibir `wallet.created`, `deposit.confirmed`, `withdraw.completed`,
   `transfer.completed` y `conversion.executed` en tiempo real, en vez de hacer
   polling. Cada webhook llega firmado con el mismo esquema HMAC (headers
   `x-timestamp`/`x-signature`, pero con **tu** `webhook_secret`, distinto del
   `hmac_secret` de tus requests salientes) — verifica la firma antes de
   procesar el payload.

## 5. Partner Treasury — fondeo

`withdraw` y `transfer` se descuentan de un saldo prepagado en USD (Partner
Treasury), no de la liquidez general de Bitalcer. Dos formas de fondearlo:

- Wire transfer internacional a la cuenta bancaria de Bitalcer.
- Transferencia on-chain de USDT (vía BSC o Polygon) a la wallet madre
  correspondiente, con un fee de conveniencia escalonado según volumen.

Contacta a tu ejecutivo de cuenta para coordinar el fondeo — la confirmación
manual (wire) o la detección automática (on-chain) acreditan el saldo, visible
en `GET /partner/v1/treasury/balance` y en la pestaña "Partner Treasury" del
dashboard.

## 6. Rate limits

Cada partner tiene un límite de requests por minuto (`rate_limit_per_minute`,
configurable según tu plan). Si lo excedes, recibes `429 too_many_requests`
con un header `Retry-After` indicando cuántos segundos esperar. Diseña tu
integración para reintentar con backoff, no en loop inmediato.

## 7. Pasar a producción

1. Completa pruebas end-to-end en sandbox: alta de usuario, wallet, depósito
   real en testnet, retiro, conversión, y recepción correcta de webhooks.
2. Contacta a tu ejecutivo de cuenta para solicitar el paso a producción.
   Esto incluye: fondeo inicial del Partner Treasury de producción, revisión
   final de tu integración, y la emisión de tus credenciales de producción
   (par `api_key`/`hmac_secret` independiente del de sandbox).
3. Las credenciales de producción mueven fondos reales — sigue el checklist de
   seguridad antes de pasar el switch.
