Receta
Pon la firma dentro de tu app
Objetivo: Tu usuario firma sin salir de tu página, en una sesión de firma que solo se abre desde tu dominio.
Grabado en el entorno interno de AllSign con una key de sandbox · backend 24c0469 · · test docs-checks-v3/tests/recetas/firma-embebida-en-tu-app.receta.spec.ts
Los ejemplos usan $ALLSIGN_API_KEY. Defínela una vez con tu key de sandbox: export ALLSIGN_API_KEY="allsign_test_sk_…" (en PowerShell: $env:ALLSIGN_API_KEY="allsign_test_sk_…").
1 Crea el documento con su firmante y su caja de firma
POST /documents ver en la referencia
Qué haces
Todo lo que lleva tu API key pasa en tu backend: crear, enviar y abrir la sesión. El navegador nunca ve la key.
Qué mirar
id="doc_e6d57f83692e4ff5ad07f57f6bd6a117"status="draft"
2 Envíalo sin mandar invitaciones
POST /documents/{document_id}/send ver en la referencia
Qué haces
recipients vacío pasa el documento a awaiting_signatures sin mandarle correo a nadie: la firma va a pasar dentro de tu página. Si lo envías sin recipients, AllSign invita por correo a cada firmante.
Qué mirar
status="awaiting_signatures"
En producción
Con una key live este envío consume créditos aunque no invite a nadie; en sandbox no se cobra nada.
3 Confirma que nadie recibió invitación
GET /documents/{document_id}/signers ver en la referencia
Qué haces
pending: el firmante está en espera y no se le mandó nada. Con un envío normal aquí verías sent.
Qué mirar
data.0.status="pending"
4 Abre una sesión de firma para ese firmante
POST /signing-sessions ver en la referencia
Qué haces
allowedOrigins dice qué páginas pueden mostrar la firma. A tu frontend solo le pasas el clientSecret: dura 15 minutos y sirve para una sola sesión, así que pídelo cuando tu usuario vaya a firmar.
Qué mirar
id="ses_b702eecc5b8d4dd0a6b58d5a5f2c8f5a"clientSecret="<client-secret>"expiresAt="2026-07-11T18:15:01.869000Z"
5 AllSign hace el equivalente por ti: revisa la política de orígenes
GET /signing-sessions/{session_id}/policy sin API key ver en la referencia
Qué haces
Tu código no llama esta operación. Cuando el SDK abre la firma, AllSign consulta el equivalente desde su servidor y lo convierte en el encabezado Content-Security-Policy: frame-ancestors del iframe, que es lo que hace cumplir el navegador: tu página puede enmarcar la firma y cualquier otra no. Se muestra para que entiendas esa política y para depurar; localhost aparece para que pruebes en tu máquina.
Qué mirar
allowedOrigins=["https://app.ejemplo.com"]frameAncestors="https://app.ejemplo.com http://localhost:*"
En producción
Si la llamas desde el navegador de tu página, falla en el preflight de CORS con un 400: la API v3 solo acepta peticiones de navegador desde orígenes de AllSign.
6 AllSign hace el equivalente por ti: inicia la sesión
POST /signing-sessions/{session_id}/init sin API key ver en la referencia
Qué haces
Tampoco la llama tu código. Cuando ejecutas AllSign.init({ clientSecret }), el iframe de AllSign inicia la sesión con una operación equivalente que revisa lo mismo que ves aquí: que el clientSecret sea válido y que la página que abre la firma (parentOrigin) esté en tus allowedOrigins. Se muestra para que entiendas qué se revisa y para depurar; en tu frontend basta con AllSign.init({ clientSecret }) y luego session.modal(), session.inline('#contenedor') o session.slider().
Qué mirar
signatureId="sgr_fdcf573b43b24b2484b1a795ffff848f"signer={"email":"ana@ejemplo.com","name":"ana@ejemplo.com"}document={"id":"doc_e6d57f83692e4ff5ad07f57f6bd6a117","title":"Contrato de servicios — Ana Torres"}
En producción
Igual en producción. Llamarla desde el navegador de tu página falla en el preflight de CORS con un 400: de iniciar la sesión se encarga el SDK.
Errores comunes de esta receta
Errores reales que el test de esta receta provocó a propósito en sandbox, sobre sus mismos pasos. Cada uno enlaza a su explicación en Errores.
RESOURCE_NOT_FOUND · 404 · en el paso 4 (Abre una sesión de firma para ese firmante)
{
"type": "https://allsign.io/developers/docs/errors#RESOURCE_NOT_FOUND",
"title": "Not Found",
"status": 404,
"detail": "No participant with email nadie@ejemplo.com on document c2af0193-88b8-4767-be86-e9bc40106542",
"instance": "/v3/signing-sessions",
"code": "RESOURCE_NOT_FOUND",
"requestId": "req_243a82a23c1a45aba4757d8ed3758d31"
}Grabado en el entorno interno de AllSign con una key de sandbox · backend 24c0469 · · test docs-checks-v3/tests/recetas/firma-embebida-en-tu-app.receta.spec.ts
PERMISSION_DENIED · 403 · en el paso 6 (AllSign hace el equivalente por ti: inicia la sesión)
Así responde la API cuando la página que abre la firma no está en allowedOrigins; en tu página lo vas a ver de otra forma. Lo normal es que el navegador ni cargue el iframe y la consola muestre un error de Content-Security-Policy frame-ancestors. Si llega a cargar, la llamada con la que el iframe inicia la sesión responde 403 con el código ORIGIN_NOT_ALLOWED. En los dos casos, agrega ese origen exacto (esquema, dominio y puerto) a allowedOrigins al abrir la sesión.
{
"type": "https://allsign.io/developers/docs/errors#PERMISSION_DENIED",
"title": "Permission denied",
"status": 403,
"detail": "The origin 'https://otro.ejemplo.com' is not authorized to embed this session.",
"instance": "/v3/signing-sessions/ses_ee38d79b09ad45b9ad094034c1910ecc/init",
"code": "PERMISSION_DENIED",
"requestId": "req_beaface9931b45e4a4eb9e51c8b13f9c"
}Grabado en el entorno interno de AllSign con una key de sandbox · backend 24c0469 · · test docs-checks-v3/tests/recetas/firma-embebida-en-tu-app.receta.spec.ts
Siguiente
- Recibe y verifica los webhooks de AllSign — Un endpoint que recibe los eventos de AllSign, comprueba que de verdad los firmó AllSign y sobrevive a sus propias caídas y a la rotación del secreto.