# Guía de Integración — API de Partners
> Flujo completo para integrar Firma Digital como partner — emitir códigos de compra, canjear identidad, y obtener el certificado.
Esta guía cubre el ciclo de vida completo de un código de compra: emitirlo, canjearlo (validar la identidad del titular), y obtener el certificado ya emitido. Hay dos APIs separadas, en dos servidores distintos:
- **API de Códigos de Compra** (`partner-pcode`, Cloudflare Worker, `/api/partner/v1`) — genera y lista códigos de compra.
- **API de Partners** (`/api/partners/v1`) — canjea identidad y entrega certificados.
## 1. Tu configuración determina el flujo, no el endpoint
A diferencia de versiones anteriores de esta API, **hay un solo endpoint de canje** (`certificate_request`). Su comportamiento se ajusta automáticamente según tu configuración de partner:
| Tu configuración | Qué pasa en `certificate_request` |
| --- | --- |
| `require_cedula_serie = 0` (flujo completo, default) | Debes enviar `names`/`fLastname`/`phone`. Se valida contra Clave Única además de Registro Civil. |
| `require_cedula_serie = 1` (flujo reducido) | **No** envíes `names`/`fLastname`/`phone` — se obtienen de Registro Civil. Debes enviar `serialNumber` (serie de la cédula). Sin Clave Única. |
| `mode = 1` (B2C, default) | El certificado se entrega recién cuando llames `certificate_claim`. |
| `mode = 2` (B2B) | El certificado se genera y se entrega automático (webhook/email) en la misma llamada a `certificate_request` — **no llames `certificate_claim`**, siempre te va a responder "ya emitido". |
Estos dos ajustes son independientes entre sí — puedes tener flujo reducido + B2B, flujo completo + B2C, o cualquier otra combinación. Contacta a soporte para configurarlos.
## 2. Flujo B2C (el más común)
1. **Emitir un código de compra** — `POST /pcode` en la API de Códigos de Compra.
```bash
curl -X POST https://partner-pcode.tsp.workers.dev/api/partner/v1/pcode \
-H "x-gw: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"productCode": "FV01", "external_reference_id": "orden-12345"}'
```
Esta llamada puede fallar con `400` si tu partner no tiene ese `productCode` habilitado — cada partner puede tener restringido a qué productos (`FV00`-`FV03`) tiene acceso. Si no te queda claro qué productos tenés habilitados, contactá a soporte.
2. **Canjear el código de compra** — `POST /certificate_request`. Los campos varían según tu flujo (ver tabla arriba). Ejemplo con flujo reducido:
```bash
curl -X POST https://api.firma.digital/api/partners/v1/certificate_request \
-H "x-gw: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pCode": "MIPARTNER-26-FV01-A1B2C3D4",
"referenceId": "orden-12345",
"dni": "18925910-7",
"serialNumber": "536463312",
"email": "usuario@ejemplo.com",
"pin": "1234"
}'
```
La respuesta trae `status: "VALIDATED"` — el certificado **todavía no existe**, solo se verificó la identidad.
3. **Obtener el certificado** — `POST /certificate_claim`, con el mismo `pin` usado en el paso anterior (funciona como contraseña del PFX).
```bash
curl -X POST https://api.firma.digital/api/partners/v1/certificate_claim \
-H "x-gw: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"p_code": "MIPARTNER-26-FV01-A1B2C3D4", "dni": "18925910-7", "pin": "1234"}'
```
Esta llamada es **de una sola vez**: si la repites, responde `201` con `ALREADY_ISSUED` en vez de regenerar el certificado. Si necesitas recuperarlo después de reclamado, contacta a soporte.
## 3. Flujo B2B
Igual al paso 1 y 2 de arriba, pero el paso 2 ya es el último: si tu configuración tiene `mode = 2`, la respuesta de `certificate_request` viene con `status: "EMITTED"` y el certificado se entrega automáticamente por el webhook y/o email que tengas configurado — pueden ser ambos a la vez, no es uno u otro. No hay paso 3.
## 4. Consultar estado
`GET /status?p_code=...` — útil sobre todo si integraste vía **widget** (el usuario completa el flujo en su navegador, no en una sola llamada tuya) y necesitas saber en qué va sin escuchar los eventos del widget en tiempo real.
```bash
curl "https://api.firma.digital/api/partners/v1/status?p_code=MIPARTNER-26-FV01-A1B2C3D4" \
-H "x-gw: $API_KEY"
```
Estados posibles, en orden de precedencia (el primero que aplica gana):
| Estado | Significa |
| --- | --- |
| `CANCELLED` | Anulado (orden cancelada) — gana incluso sobre un certificado ya emitido. |
| `EXPIRED` | El certificado se emitió pero ya venció. |
| `EMITTED` | Certificado generado y entregado. |
| `LOCKED` | Bloqueado antes de llegar a emitirse — si ya se había emitido, no aparece: sigue mostrando `EMITTED`. |
| `IN_ONBOARDING` | El usuario está a mitad del flujo del widget. |
| `VALIDATED` | Identidad verificada (solo B2C), falta llamar `certificate_claim`. |
| `ACTIVE` | Existe, nadie lo canjeó todavía. |
| `NOT_FOUND` | El código de compra no existe. |
## 5. Errores comunes
| Código | Causa |
| --- | --- |
| `401` | API Key inválida o ausente. |
| `404` | El código de compra no existe (o, en `certificate_claim`, existe pero nunca pasó por `certificate_request`). |
| `406` | Rechazo de negocio — el mensaje (`message`) indica cuál: serie requerida, RUT no coincide, email duplicado, cédula no coincide con Registro Civil, fecha de vencimiento no coincide, etc. |
| `423` | El código de compra está bloqueado de forma permanente (anulado). |
| `429` | Rate limit — 10 emisiones por minuto por partner, o intentos de validación de cédula agotados (bloqueo de seguridad temporal). |
Ver la [Referencia de la API de Partners](/api/partners/) y la [Referencia de la API de Códigos de Compra](/api/pcode/) para el detalle completo de cada endpoint.