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:

Áreav2v3
Base URL/v2/v3 (v2 sigue viva)
Casingsnake/camel mezcladocamelCase en todo
IDsUUID crudosPrefijados opacos (doc_, tmpl_…)
Errores{error:{code:E1xxx}}RFC 9457 problem+json
PaginaciónVarias formasUn envelope cursor unificado
EstadosMAYÚSCULAS_ESlowercase_en
HeadersSolo X-RateLimit-*Request-id, versión, rate limit IETF…
Status codesAlgunos malCorregidos (404 no 500…)
Webhookssnake_case + X-AllSign-SignatureCohorte 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_atcreatedAt, signer_statussignerStatus, guest_linkguestLink.

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).

PrefijoRecurso
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" }
  ]
}

Catálogo completo de códigos en Errores.

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:

v2v3
ESPERANDO_FIRMASawaiting_signatures
TODOS_FIRMARONcompleted
SELLOS_PDF / RECOLECTANDO_FIRMANTESdraft
ANULADOvoided

Recuerda que DocumentStatus y SignerStatus son x-extensible-enum: maneja valores nuevos sin romperte (ver Versionado).

Headers

La v3 agrega headers nuevos (en v2 solo existían los X-RateLimit-*). Vale la pena instrumentarlos:

HeaderPara qué
AllSign-Request-IdCorrelación: cítalo al reportar un problema (también en requestId del error).
AllSign-VersionLa versión fechada activa (ver Versionado).
RateLimit-*Límite, restante y reinicio (ver Rate limits).
Idempotency-Replayedtrue 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:

  • templateId malformado → 400 INVALID_ID (antes 500).
  • GET /v3/users/me nunca responde 403: si tu key es válida, te ves a ti mismo.
  • Acceso cross-tenant (un id que no es tuyo) → 404, no 403: 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: cuerpo snake_case congelado byte a byte, cabeceras X-AllSign-Event / X-AllSign-Event-Id / X-AllSign-Timestamp, y (con HMAC habilitado) la firma X-AllSign-Signature = HMAC-SHA256 en hex de "{timestamp}.{body}", con los bytes literales del secreto como llave.
  • Un endpoint creado con POST /v3/webhooks nace en la cohorte v3 (versión fechada 2026-07-11): sobre camelCase y 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 expone apiVersion.
  • Algunos eventos cambian de nombre entre cohortes (p.ej. signature.reminder_sentsigner.reminder_sent), y ambas cohortes traen la cabecera AllSign-Livemode — para la clásica es la única señal de entorno.

El detalle completo (tabla lado a lado, nacimiento y reintentos por cohorte) está en Webhooks → Las dos cohortes.

Checklist

Diez pasos para migrar sin sorpresas:

  1. Cambia la base URL de /v2 a /v3 (la misma API key sigue funcionando).
  2. Pasa todas tus claves a camelCase (request y response).
  3. Trata los IDs como cadenas opacas con prefijo; no parsees su interior.
  4. Reescribe el manejo de errores a problem+json; programa contra code.
  5. Lee errors[] (con pointer) en los 422 de validación.
  6. Adopta el envelope cursor: data + hasMore + nextCursor.
  7. Remapea los estados a lowercase_en y tolera valores nuevos en los enums extensibles.
  8. Instrumenta los headers nuevos (AllSign-Request-Id, RateLimit-*, Idempotency-Replayed) y deja de leer los X-* legacy (X-RateLimit-Reset es epoch, no delta).
  9. Ajusta tu manejo de status codes (404 en vez de 500; /users/me nunca 403; cross-tenant → 404).
  10. 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.