Migrar de v2 a v3
La v3 es un re-ordenamiento, no una reescritura. Los mismos recursos y la
misma lógica de negocio, con un contrato consistente encima. Tu misma API key funciona en
ambas. La v2 sigue viva y congelada en /v2: migra a tu ritmo, endpoint por
endpoint.
De un vistazo
Nueve cambios, todos mecánicos. Ninguno cambia qué hace la API, solo cómo la lees:
| Área | v2 | v3 |
|---|---|---|
| Base URL | /v2 | /v3 (v2 sigue viva) |
| Casing | snake/camel mezclado | camelCase en todo |
| IDs | UUID crudos | Prefijados opacos (doc_, tmpl_…) |
| Errores | {error:{code:E1xxx}} | RFC 9457 problem+json |
| Paginación | Varias formas | Un envelope cursor unificado |
| Estados | MAYÚSCULAS_ES | lowercase_en |
| Headers | Solo X-RateLimit-* | Request-id, versión, rate limit IETF… |
| Status codes | Algunos mal | Corregidos (404 no 500…) |
| Webhooks | snake_case + X-AllSign-Signature | Cohorte v3: camelCase + Standard Webhooks (los clásicos no cambian) |
Base URL
Cambia el prefijo de la ruta de /v2 a /v3. Eso es todo lo obligatorio para
empezar: https://api.allsign.io/v3/.... La misma API key
(allsign_live_sk_ / allsign_test_sk_) autentica en ambas versiones — no generes
keys nuevas. La v2 no se apaga: está congelada (sin cambios de comportamiento) y puedes
migrar un endpoint a la vez.
Casing
La v2 mezclaba snake_case y camelCase según el endpoint. La v3 es
camelCase en todo — request y response, sin excepciones. Renombra tus claves:
created_at → createdAt, signer_status → signerStatus,
guest_link → guestLink.
IDs
Los UUID crudos se vuelven identificadores opacos con prefijo. Son cadenas
opacas: no parsees su interior, solo guárdalas y reenvíalas. Un id malformado responde
400 INVALID_ID (antes de tocar la base de datos).
| Prefijo | Recurso |
|---|---|
doc_ | Documento |
tmpl_ | Plantilla |
fld_ | Campo (field) |
ses_ | Sesión de firma |
usr_ | Usuario |
whe_ | Webhook endpoint |
evt_ | Evento |
whsec_ | Secreto de firma de webhook |
Errores
El envelope propietario de v2 desaparece. La v3 usa RFC 9457
application/problem+json, con code en UPPER_SNAKE_CASE
(estable) en vez del E1xxx numérico. Programa contra code, nunca contra el texto.
Antes (v2)
{
"error": {
"code": "E1300",
"message": "document not found"
}
}Ahora (v3)
{
"type": "https://developers.allsign.io/errors#DOCUMENT_NOT_FOUND",
"title": "Document not found",
"status": 404,
"detail": "No document exists with id doc_...",
"code": "DOCUMENT_NOT_FOUND",
"requestId": "req_..."
}La validación semántica responde 422 con un arreglo errors[]: un objeto por
campo con field y su pointer (JSON Pointer).
{
"type": "https://developers.allsign.io/errors#VALIDATION_ERROR",
"title": "Validation failed",
"status": 422,
"code": "VALIDATION_ERROR",
"errors": [
{ "field": "signers[0].email", "pointer": "/signers/0/email",
"code": "INVALID_VALUE", "detail": "not a valid email address" }
]
}
Paginación
Las varias formas de paginar de v2 se unifican en un solo envelope basado en cursor:
los recursos vienen en data, con hasMore y nextCursor. Para la
siguiente página, reenvía nextCursor como startingAfter hasta que
hasMore sea false.
GET /v3/documents?limit=20&startingAfter=djF8Y3JlYXRlZEF0fC4uLg
{
"object": "list",
"data": [ { "id": "doc_..." }, { "id": "doc_..." } ],
"hasMore": true,
"nextCursor": "djF8Y3JlYXRlZEF0fC4uLg",
"limit": 20
}
Estados
Los estados pasan de MAYÚSCULAS_ES (español) a lowercase_en (inglés). Actualiza
tus comparaciones y tus mappings de UI:
| v2 | v3 |
|---|---|
ESPERANDO_FIRMAS | awaiting_signatures |
TODOS_FIRMARON | completed |
SELLOS_PDF / RECOLECTANDO_FIRMANTES | draft |
ANULADO | voided |
Headers
La v3 agrega headers nuevos (en v2 solo existían los X-RateLimit-*). Vale la pena
instrumentarlos:
| Header | Para qué |
|---|---|
AllSign-Request-Id | Correlación: cítalo al reportar un problema (también en requestId del error). |
AllSign-Version | La versión fechada activa (ver Versionado). |
RateLimit-* | Límite, restante y reinicio (ver Rate limits). |
Idempotency-Replayed | true cuando una respuesta salió del caché de idempotencia, no de una ejecución nueva. |
Los X-* no desaparecieron del cable. Por compatibilidad,
las respuestas v3 traen además los headers legacy X-Allsign-Request-Id y el trío
X-RateLimit-*. Y ojo con la trampa: X-RateLimit-Reset conserva su semántica
v2 —un epoch (timestamp Unix absoluto)—, mientras que RateLimit-Reset
es un delta en segundos. Un cliente que lea X-RateLimit-Reset esperando
un delta va a calcular esperas de décadas. Al migrar, lee solo los headers nuevos.
Status codes
Se corrigieron códigos que en v2 mentían. Si tu cliente v2 trataba un 500 como "reintenta",
revisa estos:
templateIdmalformado →400 INVALID_ID(antes500).GET /v3/users/menunca responde403: si tu key es válida, te ves a ti mismo.- Acceso cross-tenant (un id que no es tuyo) →
404, no403: no revelamos que el recurso existe.
Webhooks
Migrar tus llamadas a /v3 no cambia tus webhooks. El formato
de cada endpoint de webhook lo decide su propia versión de contrato (apiVersion), y hoy
hay dos cohortes:
- Tus destinos existentes son la cohorte clásica (
v2legacy) y así se quedan: cuerposnake_casecongelado byte a byte, cabecerasX-AllSign-Event/X-AllSign-Event-Id/X-AllSign-Timestamp, y (con HMAC habilitado) la firmaX-AllSign-Signature= HMAC-SHA256 en hex de"{timestamp}.{body}", con los bytes literales del secreto como llave. - Un endpoint creado con
POST /v3/webhooksnace en la cohorte v3 (versión fechada2026-07-11): sobrecamelCasey firma Standard Webhooks (webhook-id/webhook-timestamp/webhook-signature) — la fórmula y la llave de verificación cambian, así que tu verificador clásico no sirve tal cual. - Uno creado desde el dashboard hereda el formato de tu cuenta: si ya tienes
destinos clásicos, nace
v2legacy(para no romper el handler que ya tienes); una cuenta que estrena integración nace en v3. - Cambiar un endpoint de cohorte hoy solo se puede desde el dashboard —
PATCH /v3/webhooks/{id}no exponeapiVersion. - Algunos eventos cambian de nombre entre cohortes (p.ej.
signature.reminder_sent→signer.reminder_sent), y ambas cohortes traen la cabeceraAllSign-Livemode— para la clásica es la única señal de entorno.
Checklist
Diez pasos para migrar sin sorpresas:
- Cambia la base URL de
/v2a/v3(la misma API key sigue funcionando). - Pasa todas tus claves a
camelCase(request y response). - Trata los IDs como cadenas opacas con prefijo; no parsees su interior.
- Reescribe el manejo de errores a
problem+json; programa contracode. - Lee
errors[](conpointer) en los422de validación. - Adopta el envelope cursor:
data+hasMore+nextCursor. - Remapea los estados a
lowercase_eny tolera valores nuevos en los enums extensibles. - Instrumenta los headers nuevos (
AllSign-Request-Id,RateLimit-*,Idempotency-Replayed) y deja de leer losX-*legacy (X-RateLimit-Resetes epoch, no delta). - Ajusta tu manejo de status codes (404 en vez de 500;
/users/menunca 403; cross-tenant → 404). - Decide la cohorte de tus webhooks: los destinos clásicos siguen en
v2legacy; un endpoint nuevo por API nace v3 y se verifica con Standard Webhooks.