JS SDK Reference
Referencia completa de @allsign/embedded — inspirado en Plaid Link moderno y Typeform Embed. Modelo client_secret-only: una sola credencial pública, efímera, scoped a una session.
Instalación
npm install @allsign/embedded
O vía CDN para proyectos sin bundler (disponible al publicar la v1):
<script src="https://js.allsign.io/v1.js" async></script>
El CDN js.allsign.io/v1.js estará disponible al publicar la v1. En la versión actual (@allsign/embedded 0.3.x) instala vía npm. La carga en 2 fases (un loader ligero de menos de 3 KB que expone la API + el runtime completo bajo demanda) es la arquitectura objetivo del SDK; en 0.3.x el core aún no se carga por import dinámico bajo demanda, así que no la asumas como garantía de performance todavía.
Inicialización
import { AllSign } from '@allsign/embedded';
const session = AllSign.init({
clientSecret: 'as_sess_xxx_secret_yyy',
// callbacks y opciones (ver tabla más abajo)
});
El clientSecret es la única credencial que el frontend maneja. Es efímero (15 min), single-use y scoped a una sola firma — lo genera tu backend con POST /v2/signing-sessions usando tu secret key, y lo pasas al frontend. Tu secret key nunca sale del backend.
¿Por qué no hay publishable key? Porque no aporta nada: el clientSecret ya encoda el session_id y el tenant, y el env (live vs test) se infiere del bundle del SDK y del test_mode que devuelve el init. Seguimos el modelo Plaid moderno (post-2020) que deprecó su publicKey por la misma razón, no el modelo Stripe que requiere pk para tokenización originada en el browser — nuestro browser nunca crea nada antes de que exista una session.
Modos de embedding
Todas las funciones de montaje son métodos del objeto session devuelto por AllSign.init(). Las opciones visuales (locale, theme, values) se pasan en init; los métodos de montaje solo reciben el contenedor o config de posicionamiento.
session.modal()
Abre un overlay fullscreen sobre tu aplicación. El más fácil de integrar — no necesitas un contenedor.
const session = AllSign.init({
clientSecret: 'as_sess_xxx_secret_yyy',
locale: 'es-MX',
theme: { primaryColor: '#1a73e8' },
onSuccess: (result) => { /* firmado */ },
onExit: (metadata) => { /* cerró */ },
onEvent: (event) => { /* progreso */ },
});
session.modal();
session.inline(container)
Monta el widget dentro de un elemento DOM que tú controlas. Ideal cuando la firma es parte de tu layout.
const session = AllSign.init({
clientSecret: 'as_sess_xxx_secret_yyy',
locale: 'es-MX',
values: { nombre: 'Juan', rfc: 'ABC123' },
onSuccess: (result) => { /* firmado */ },
});
session.inline('#firma-container');
<div id="firma-container" style="width: 100%; height: 600px;"></div>
El widget comunica su altura al parent y se auto-redimensiona para evitar doble scroll.
Para la mejor experiencia, el contenedor debe tener al menos 500px de ancho y 500px de alto. El widget es responsive y se adapta, pero contenedores muy pequeños degradan la experiencia.
session.slider(options)
const session = AllSign.init({
clientSecret: 'as_sess_xxx_secret_yyy',
onSuccess: (result) => { /* firmado */ },
});
session.slider();
En la versión actual (0.3.x), slider() se comporta igual que modal() — reusa el layout de modal. El panel lateral (drawer) con opciones position ('left' / 'right') y width está planeado para una versión futura; por ahora esas opciones se ignoran.
Opciones de AllSign.init()
Estas son todas las opciones que puedes pasar al crear la session:
| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
clientSecret | string | ✅ | — | El client_secret de tu Signing Session (creado en tu backend con POST /v2/signing-sessions) |
locale | 'es-MX' | 'en-US' | — | 'es-MX' | Idioma de la interfaz |
theme | ThemeOptions | — | — | Personalización visual |
values | Record<string, string> | — | — | Pre-fill de variables del template desde el frontend |
allowCancel | boolean | — | true | Reservado — sin efecto en la versión actual (0.3.x). El modal siempre permite cerrar (botón + click en el backdrop). |
onSuccess | (result: SigningResult) => void | — | — | Se dispara al instante en que el firmante completa su firma. El iframe NO se cierra aquí — muestra la vista post-firma; no lo destruyas si quieres que la vean |
onExit | (metadata: ExitMetadata) => void | — | — | Se dispara cuando la sesión termina (cualquier razón). Para 'completed' es diferido: ocurre cuando el firmante cierra la vista post-firma ("Cerrar") |
onEvent | (event: SigningEvent) => void | — | — | Se dispara en cada paso del flujo (OTP, IDV, firma) |
onEvidence | (evidence: SigningEvidence) => void | — | — | Se dispara cuando el PDF de evidencia está listo (todos firmaron). Trae downloadUrl presignado |
onReady | () => void | — | — | Se dispara cuando el widget terminó de cargar |
ThemeOptions
| Propiedad | Tipo | Descripción |
|---|---|---|
primaryColor | string | Color principal — botones, links, acentos (hex) |
backgroundColor | string | Color de fondo del widget |
buttonText | string | Texto del botón principal (default: "Firmar documento") |
logo | string | URL de tu logo (se muestra en el header) |
React Hook: useAllSignLink
El hook para React elimina todo el boilerplate. Inspirado en usePlaidLink.
npm install @allsign/embedded
import { useAllSignLink } from '@allsign/embedded/react';
function SignButton({ clientSecret }) {
const { open, ready, error } = useAllSignLink({
clientSecret,
mode: 'modal', // 'modal' | 'slider'
onSuccess: (result) => {
// result.signatureId — UUID de la firma
// result.documentId — UUID del documento
// result.signedAt — timestamp ISO-8601
console.log('Firmado:', result.signatureId);
},
onExit: (metadata) => {
// metadata.reason — 'completed' | 'cancelled' | 'expired' | 'error'
// metadata.lastStep — último paso completado ('otp', 'id_scan', 'signature')
console.log('Salió en:', metadata.lastStep);
},
onEvent: (event) => {
// Eventos granulares para analytics y UI
// event.name — 'OTP_SENT', 'OTP_VERIFIED', 'ID_SCAN_STARTED',
// 'ID_SCAN_COMPLETED', 'DOCUMENT_VIEWED',
// 'SIGNATURE_DRAWN', 'SIGNATURE_SUBMITTED'
// event.timestamp — ISO-8601
// event.metadata — datos adicionales del paso
console.log('Evento:', event.name);
},
});
if (error) return <p>Error: {error.message}</p>;
return (
<button onClick={open} disabled={!ready}>
Firmar documento
</button>
);
}
Hook API
| Propiedad | Tipo | Descripción |
|---|---|---|
open | () => void | Abre la sesión de firma |
ready | boolean | true cuando el SDK cargó y el clientSecret es válido |
error | Error | null | Error de inicialización (secret inválido, expirado, etc.) |
Callbacks detallados
onSuccess(result)
Se dispara cuando el firmante completó su firma. Úsalo para feedback instantáneo en tu UI.
interface SigningResult {
signatureId: string; // UUID de la firma
documentId: string; // UUID del documento
signerEmail: string; // Email del firmante
signedAt: string; // Timestamp ISO-8601
}
onExit(metadata)
Se dispara siempre que la sesión termina, sin importar la razón. Es tu "catch-all" para cleanup.
interface ExitMetadata {
reason: 'completed' | 'cancelled' | 'expired' | 'error';
lastStep: 'otp' | 'id_scan' | 'variables' | 'document_view' | 'signature' | null;
sessionId: string;
documentId: string;
error?: {
code: string;
message: string;
};
}
lastStep te dice exactamente dónde abandonó el firmante — útil para analytics y para mostrar el paso correcto si vuelve a intentar.
onEvent(event)
Se dispara en cada paso del flujo. Granular, ideal para analytics y para mostrar progreso en tu UI.
interface SigningEvent {
name: string; // Nombre del evento
timestamp: string; // ISO-8601
metadata: Record<string, any>;
}
Eventos disponibles:
| Evento | Cuándo se dispara |
|---|---|
SESSION_STARTED | El widget se montó y cargó |
OTP_SENT | Se envió el código OTP (si está configurado) |
OTP_VERIFIED | El firmante verificó su OTP |
ID_SCAN_STARTED | Inició escaneo de identificación |
ID_SCAN_COMPLETED | Escaneo de INE completado |
SELFIE_CAPTURED | Selfie capturada para face match |
BIOMETRIC_VERIFIED | Face match exitoso (INE vs selfie) |
VARIABLES_FILLED | El firmante completó las variables del formulario |
DOCUMENT_VIEWED | El firmante vio el documento |
SIGNATURE_DRAWN | El firmante dibujó su firma |
SIGNATURE_SUBMITTED | La firma se envió al servidor |
SESSION_COMPLETED | Todo el flujo terminó exitosamente |
Métodos de instancia
session.close()
Cierra la sesión de firma y destruye el iFrame.
const session = AllSign.init({ clientSecret: '...' });
session.inline('#container');
// Después...
session.close();
session.unmount()
Desmonta el widget del DOM sin cerrar la sesión. Útil para cleanup en React.
useEffect(() => {
const session = AllSign.init({ clientSecret });
session.inline('#container');
return () => session.unmount();
}, [clientSecret]);
HTML Data Attributes (no-code) — no disponible aún
El auto-mount por atributos data-allsign-* no está implementado en la versión actual del SDK (@allsign/embedded 0.3.x). El SDK no lee atributos data-allsign-* ni despacha custom events del DOM (allsign:success / allsign:exit). La única vía soportada es JavaScript: AllSign.init({ clientSecret }).modal() / .inline() / .slider() con los callbacks onSuccess / onExit / onEvent. Esta sección queda como roadmap.
TypeScript
El SDK incluye tipos completos:
import type {
AllSignSession,
AllSignInitOptions,
SigningResult,
ExitMetadata,
SigningEvent,
ThemeOptions,
} from '@allsign/embedded';
import type {
UseAllSignLinkOptions,
UseAllSignLinkReturn,
} from '@allsign/embedded/react';
Manejo de errores
Los errores te llegan por dos canales: excepción síncrona de AllSign.init() (AllSignError, validación local) y metadata.error.code en onExit (errores en tiempo de ejecución dentro del iframe). Desde 0.3.0 el SDK exporta isRetryableError(code) / isTerminalError(code) para decidir la recuperación sin memorizar códigos:
import { AllSign, isRetryableError } from '@allsign/embedded';
const session = AllSign.init({
clientSecret: '...',
onExit: async (metadata) => {
const code = metadata.error?.code;
if (!code) return; // salida limpia (completada / cancelada por el firmante)
if (isRetryableError(code)) {
// Transitorio (NETWORK_ERROR, BACKEND_UNREACHABLE, INTERNAL_ERROR,
// INIT_TIMEOUT, HTTP_5xx…): el MISMO client_secret sigue siendo
// válido dentro de su ventana de 15 min — re-invoca init con backoff.
setTimeout(() => reintentar(clientSecret), 2000);
} else {
// Terminal (SESSION_EXPIRED, SESSION_CANCELLED, ORIGIN_NOT_ALLOWED…):
// pide a TU backend una sesión NUEVA y re-invoca init con el
// client_secret fresco.
refreshSession();
}
},
});
Códigos de error
La taxonomía completa — cada código con su HTTP, quién lo emite (SDK, proxy, backend o iframe), si es terminal o reintentable, y la acción recomendada — vive en Errores del flujo embebido. Los que verás con más frecuencia:
| Código | Tipo | Descripción |
|---|---|---|
MISSING_CLIENT_SECRET | Terminal | No pasaste clientSecret a AllSign.init(). |
SECRET_KEY_PASSED_AS_CLIENT_SECRET | Terminal | Pasaste una secret key (allsign_live_sk_*) donde iba el client_secret — bug de seguridad, corrígelo. |
SESSION_EXPIRED | Terminal | El client_secret expiró (>15 min). Crea una sesión nueva en tu backend. |
SESSION_INVALID | Terminal | Token inválido o no reconocido por el servidor. |
SESSION_COMPLETED | Terminal | La sesión ya se completó — trátalo como éxito. |
ORIGIN_NOT_ALLOWED | Terminal | Tu origen no está en allowed_origins de la sesión. |
NETWORK_ERROR | Reintentable | Falla de red — reintenta con el mismo client_secret. |
INTERNAL_ERROR | Reintentable | Error inesperado del lado de AllSign — reintenta; si persiste, sesión nueva + reporte. |
El SDK pasa los códigos del iframe verbatim (no normaliza), así que puedes recibir códigos que no aparecen en esta tabla corta — por ejemplo los del pipeline de verificación (VERIFICATION_FAILED) o los fallback HTTP_{status}. Todos están catalogados en Errores del flujo embebido, y los códigos desconocidos clasifican como terminales.
Compatibilidad
| Browser | Versión mínima |
|---|---|
| Chrome | 80+ |
| Firefox | 78+ |
| Safari | 14+ |
| Edge | 80+ |
| Mobile Safari (iOS) | 14+ |
| Chrome Android | 80+ |
Siguiente paso
- Personalización — Branding, temas y locale
- Eventos y Callbacks — Eventos client-side + webhooks server-side
- Seguridad — Sessions, CSP y validación
- Errores — Taxonomía completa y patrón de recuperación

