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
Ocho 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…) |
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. |
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.
Checklist
Nueve 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). - Ajusta tu manejo de status codes (404 en vez de 500;
/users/menunca 403; cross-tenant → 404).