Integration Guide — Partner API
This guide covers the full lifecycle of a purchase_code: issuing it, redeeming it (validating the holder’s identity), and retrieving the already-issued certificate. There are two separate APIs, on two different servers:
- Purchase Code API (
partner-pcode, Cloudflare Worker,/api/partner/v1) — generates and lists purchase_codes. - Partner API (
/api/partners/v1) — redeems identity and delivers certificates.
1. Your configuration decides the flow, not the endpoint
Section titled “1. Your configuration decides the flow, not the endpoint”Unlike previous versions of this API, there is a single redeem endpoint (certificate_request). Its behavior adapts automatically based on your partner configuration:
| Your configuration | What happens in certificate_request |
|---|---|
require_cedula_serie = 0 (full flow, default) |
You must send names/fLastname/phone. Validated against Clave Única in addition to the civil registry. |
require_cedula_serie = 1 (reduced flow) |
Don’t send names/fLastname/phone — they come from the civil registry. You must send serialNumber (ID card serial). No Clave Única. |
mode = 1 (B2C, default) |
The certificate is only delivered once you call certificate_claim. |
mode = 2 (B2B) |
The certificate is generated and delivered automatically (webhook/email) in the same certificate_request call — don’t call certificate_claim, it will always say “already issued”. |
These two settings are independent — you can have reduced flow + B2B, full flow + B2C, or any other combination. Contact support to configure them.
2. B2C flow (the most common one)
Section titled “2. B2C flow (the most common one)”-
Issue a purchase_code —
POST /pcodeon the Purchase Code API.Ventana de terminal 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": "order-12345"}'This call can fail with
400if your partner doesn’t have thatproductCodeenabled — each partner can be restricted to a subset of products (FV00-FV03). If you’re not sure which products you have access to, contact support. -
Redeem the purchase_code —
POST /certificate_request. Which fields you send depends on your flow (see table above). Example with the reduced flow:Ventana de terminal curl -X POST https://api.firma.digital/api/partners/v1/certificate_request \-H "x-gw: $API_KEY" \-H "Content-Type: application/json" \-d '{"pCode": "MYPARTNER-26-FV01-A1B2C3D4","referenceId": "order-12345","dni": "18925910-7","serialNumber": "536463312","email": "user@example.com","pin": "1234"}'The response comes back with
status: "VALIDATED"— the certificate doesn’t exist yet, only identity was verified. -
Retrieve the certificate —
POST /certificate_claim, with the samepinused in the previous step (it doubles as the PFX’s password).Ventana de terminal 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": "MYPARTNER-26-FV01-A1B2C3D4", "dni": "18925910-7", "pin": "1234"}'This call is one-time only: calling it again responds
201withALREADY_ISSUEDinstead of regenerating the certificate. If you need to recover it after it was already claimed, contact support.
3. B2B flow
Section titled “3. B2B flow”Same as steps 1 and 2 above, except step 2 is already the last one: if your configuration has mode = 2, the certificate_request response comes back with status: "EMITTED" and the certificate is delivered automatically through your configured webhook and/or email — both can fire at once, it’s not either/or. There is no step 3.
4. Checking status
Section titled “4. Checking status”GET /status?p_code=... — most useful if you integrated via the widget (the user completes the flow in their own browser, not in a single call you make) and you need to know how far along they are without listening to widget events in real time.
curl "https://api.firma.digital/api/partners/v1/status?p_code=MYPARTNER-26-FV01-A1B2C3D4" \ -H "x-gw: $API_KEY"Possible states, in precedence order (the first one that applies wins):
| State | Meaning |
|---|---|
CANCELLED |
Voided (order cancelled) — wins even over an already-issued certificate. |
EXPIRED |
The certificate was issued but has since expired. |
EMITTED |
Certificate generated and delivered. |
LOCKED |
Blocked before it got issued — if it was already issued, this doesn’t show: it still reports EMITTED. |
IN_ONBOARDING |
The user is midway through the widget flow. |
VALIDATED |
Identity verified (B2C only), certificate_claim still pending. |
ACTIVE |
Exists, nobody has redeemed it yet. |
NOT_FOUND |
The purchase code doesn’t exist. |
5. Common errors
Section titled “5. Common errors”| Code | Cause |
|---|---|
401 |
Invalid or missing API Key. |
404 |
The purchase_code doesn’t exist (or, in certificate_claim, exists but never went through certificate_request). |
406 |
Business rejection — the message field says which: serial required, RUT mismatch, duplicate email, ID card doesn’t match the civil registry, expiration date mismatch, etc. |
423 |
The purchase_code is permanently blocked (voided). |
429 |
Rate limit — 10 emissions per minute per partner, or ID validation attempts exhausted (temporary security lock). |
See the Partner API Reference and the Purchase Code API Reference for full details on each endpoint.