Zign API v1

Integra NOM-151 y firma electrónica a tus sistemas

API REST sobre HTTPS para ERP, CRM, CLM y automatizaciones. Cada organización genera sus llaves desde Integraciones y API en el backoffice. Todas las respuestas son JSON en UTF-8 y las fechas están en UTC (ISO 8601).

OpenAPI 3.1 (JSON)Colección de PostmanValidador NOM-151Seguridad técnica y SLA

Elige tu escenario de integración

Hay dos formas de usar Zign. Identifica la tuya antes de crear la llave: define los alcances que marcas, los endpoints que llamas y el consumo de certificados.

escenario a

Firma electrónica completa

Zign gestiona el flujo: envía el documento a los firmantes, valida con OTP, recibe la firma autógrafa o la e.firma (FIEL) del SAT, sella el PDF y al cerrarse el sobre emite la constancia NOM-151 y ancla la huella en blockchain.

  • Alcances: envelopes:write, envelopes:read, webhooks:read (opcional nom151:read).
  • Endpoints: POST /envelopes, POST /envelopes/{id}/send, GET /envelopes/{id}, GET /envelopes/{id}/documents/{docId}.
  • Consumo: 1 certificado por documento firmado; la constancia NOM-151 está incluida.
  • Úsalo si: necesitas que tus clientes o empleados firmen y quieres la evidencia legal de punta a punta.
escenario b

Solo NOM-151 (conservación)

Tu plataforma ya produce el archivo final y solo necesitas la constancia de conservación de mensajes de datos con sello de tiempo del PSC acreditado. Zign no ve el flujo de firma; basta la huella del archivo.

  • Alcances: nom151:write y nom151:read.
  • Endpoints: POST /nom151/constancias, GET /nom151/constancias/{folio}, POST /nom151/validate.
  • Entrada: sha256 del archivo, o contentBase64 (máx. 20 MB) si prefieres que Zign calcule la huella.
  • Guarda: folio y constanciaBase64 como archivo .asn1 junto al documento.
NecesidadEscenarioAlcances a marcar
Recabar firmas de terceros por correoAenvelopes:write, envelopes:read
Firmar con e.firma (FIEL) del SATAenvelopes:write, envelopes:read
Conservar un PDF ya firmado o un expedienteBnom151:write, nom151:read
Verificar integridad o validar una constanciaA o Bnom151:read
Recibir notificaciones automáticasA o Bwebhooks:read

En ambos escenarios empieza con una llave de pruebas (sandbox): las constancias se emiten simuladas con folio sbx-, sin consumir certificados ni contactar al proveedor, y se pueden validar igual. Al terminar, crea la llave de producción con los mismos alcances y cambia solo el secreto. Nuestros certificados no tienen vigencia.

Inicio rápido en 5 minutos

  1. 1. En el backoffice, entra a Integraciones y API y crea una llave con los alcances nom151:write y nom151:read. El secreto se muestra una sola vez.
  2. 2. Comprueba la conexión con GET /health.
  3. 3. Calcula el SHA-256 del archivo y emite la constancia con POST /nom151/constancias.
  4. 4. Guarda folio y constanciaBase64 (archivo .asn1) junto al documento en tu sistema.
  5. 5. Verifica cuando quieras con GET /verify/{sha256} o POST /nom151/validate.
curl -X POST https://zerozign.com/api/public/v1/nom151/constancias \
  -H "Authorization: Bearer $ZIGN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sha256": "3f786850e387550fdab836ed7e6dc881de23001b3f0cbc4b0d1a4f4a1d9ca1a5",
    "fileName": "contrato-4471.pdf",
    "externalId": "ERP-4471"
  }'

Autenticación

Envía tu llave en el encabezado Authorization. Guárdala en el gestor de secretos de tu sistema y nunca en el navegador.

Authorization: Bearer cfk_1a2b3c4d_<secreto>
Content-Type: application/json

Alcances: nom151:write, nom151:read, envelopes:read, envelopes:write, webhooks:read. Límite por defecto: 120 peticiones por minuto y por llave (respuesta 429 al excederlo).

Base URL

https://zerozign.com/api/public/v1

Cómo calcular el SHA-256 correctamente

Es el error más común de integración. La huella debe calcularse sobre los bytes exactos del archivo que vas a conservar, en hexadecimal minúsculas de 64 caracteres. Si el archivo cambia aunque sea un byte (por ejemplo, al re-guardarlo o al agregar metadatos), la huella cambia y la constancia deja de corresponder.

# macOS / Linux
shasum -a 256 contrato-4471.pdf

# Windows (PowerShell)
Get-FileHash contrato-4471.pdf -Algorithm SHA256

Si prefieres que Zign la calcule, envía contentBase64 con el archivo completo (máximo 20 MB) en lugar de sha256.

Ambiente de pruebas (sandbox)

Al crear la llave, marca Llave de pruebas (sandbox). Esa llave usa los mismos endpoints y devuelve la misma estructura de respuesta, pero emite constancias simuladas: no consume certificados ni contacta al PSC. El folio inicia con sbx-, environment es sandbox y status es simulado; POST /nom151/validate también valida esas constancias simuladas. Cuando tu integración esté lista, genera una llave de producción con los mismos alcances y cambia sólo el valor del secreto.

Prueba paso a paso en Postman

La colección descargable ya trae la base URL de producción, la autorización Bearer heredada y scripts que guardan solos folio, sha256 y constanciaBase64 tras emitir la constancia.

  1. 1. Descarga la colección. Desde /api/public/v1/postman.json o con el botón “Colección de Postman” al inicio de esta página.
  2. 2. Crea tu llave sandbox. Backoffice → Integraciones y API → Crear llave → marca Llave de pruebas (sandbox) con alcances nom151:write y nom151:read. Copia el secreto cfk_…: sólo se muestra una vez.
  3. 3. Importa en Postman. Import → arrastra el archivo. Aparece la colección “Zign API v1 — NOM-151”.
  4. 4. Configura las variables. Haz clic en el nombre de la colección (no en una petición) → pestaña Variables → pega tu llave en ZIGN_API_KEY y deja baseUrl como viene → Save. Ojo: Params no es lo mismo que Variables; Params sólo agrega query string a una petición.
  5. 5. Health. Ejecuta la petición 1: responde 200 con modo, organización, alcances y saldo. Un 401 significa llave mal pegada o revocada. Agrega ?deep=1 para comprobar también al PSC.
  6. 6. Emite la constancia. Petición 2: envía sha256 (64 hex en minúsculas) o contentBase64 + fileName (≤ 20 MB). Devuelve folio (con prefijo sbx- en sandbox), hashProcessed, issuedAt y constanciaBase64.
  7. 7. Guarda folio y huella. El script de la petición 2 los escribe automáticamente en las variables de la colección. Si prefieres hacerlo a mano, copia los valores en las variables folio, sha256 y constanciaBase64. El script es:
    const r = pm.response.json();
    if (r.folio) pm.collectionVariables.set("folio", r.folio);
    if (r.hashProcessed || r.sha256)
      pm.collectionVariables.set("sha256", r.hashProcessed || r.sha256);
    if (r.constanciaBase64)
      pm.collectionVariables.set("constanciaBase64", r.constanciaBase64);
  8. 8. Recupera y lista. Peticiones 3 y 4: GET /nom151/constancias/{{folio}} y el listado paginado de tu organización.
  9. 9. Valida la constancia. Petición 5: el body ya usa {{sha256}}, {{folio}} y {{constanciaBase64}}. Envía y debes recibir valid: true. Si responde falso, revisa que los tres valores sean de la misma emisión y que el base64 esté completo (sin saltos de línea ni recortes).
  10. 10. Verificación pública. Petición 6: GET /verify/{{sha256}}, sin llave; muestra integridad, NOM-151 y blockchain.
  11. 11. Pasa a producción. Repite el flujo con una llave sin sandbox: se contacta al PSC real y se consume un certificado por constancia (idempotente por huella, no cobra dos veces la misma).

Errores frecuentes en la prueba: invalid_hash (huella mal formada), insufficient_credits (sin saldo, sólo en producción) y psc_unavailable (reintenta).

Endpoints NOM-151

GET/health

Cualquier llave válida sirve, sin alcance específico. Devuelve la organización, sus alcances, el modo (pruebas o produccion), el saldo de certificados por país y la hora del servidor. Con ?deep=1 además comprueba en vivo la disponibilidad del proveedor de certificación, sin consumir certificados.
curl "https://zerozign.com/api/public/v1/health?deep=1" -H "Authorization: Bearer $ZIGN_API_KEY"

POST/nom151/constanciasnom151:write

Emite la constancia de conservación NOM-151 de una huella, con un PSC acreditado. Consume 1 certificado. La operación es idempotente por organización y huella: repetirla devuelve 200 con la constancia existente y no consume otro certificado. Si el proveedor falla, el certificado se reversa automáticamente.
# 201 Created
{
  "sha256": "3f786850e387550fdab836ed7e6dc881de23001b3f0cbc4b0d1a4f4a1d9ca1a5",
  "folio": "b9d4f1e0-1c2a-4f7d-9a44-6f0f1f2c3d4e",
  "provider": "codex",
  "hashProcessed": "3f786850…",
  "issuedAt": "2026-08-31T05:12:44.000Z",
  "environment": "produccion",
  "fileName": "contrato-4471.pdf",
  "externalId": "ERP-4471",
  "constanciaBase64": "MIIF…",
  "status": "certificado"
}

GET/nom151/constancias/{folio}nom151:read

Recupera una constancia ya emitida. Acepta el folio del PSC o la huella SHA-256, por lo que puedes reconstruir el archivo .asn1 en cualquier momento sin guardarlo tú.

GET/nom151/constancias?page=&pageSize=nom151:read

Listado paginado de las constancias de la organización (sin el archivo, para respuestas ligeras).

POST/nom151/validatenom151:read

Valida ante el PSC una constancia que ya tengas: envía sha256, folio y constanciaBase64.
{ "valid": true, "provider": "codex", "message": "Constancia válida" }

GET/verify/{sha256}

Verificación pública, sin llave: integridad en Zign, constancia NOM-151, anclaje en blockchain y sello institucional de una huella. Ideal para portales de consulta de tus clientes.

Endpoints de firma electrónica

POST/envelopesenvelopes:write

Crea un sobre con uno o más PDF en base64 y, por defecto, lo envía a firma de inmediato (send: false lo deja en borrador). Cada archivo se certifica con NOM-151 al cerrarse el sobre.
curl -X POST https://zerozign.com/api/public/v1/envelopes \
  -H "Authorization: Bearer $ZIGN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Contrato de arrendamiento 4471",
    "message": "Favor de firmar antes del viernes.",
    "signingOrder": "paralelo",
    "expiresInDays": 15,
    "send": true,
    "externalId": "ERP-4471",
    "documents": [{ "name": "contrato.pdf", "contentBase64": "JVBERi0xLjQK..." }],
    "signers": [
      { "fullName": "Ana Ruiz", "email": "ana@cliente.com", "role": "Firmante" },
      { "fullName": "Auditoría", "email": "audit@cliente.com", "role": "Observador" }
    ]
  }'

# 201 Created
{ "id": "8f0e...", "folio": "MX-8F0E4C21", "status": "en_proceso" }

GET/envelopes?status=&page=&pageSize=envelopes:read

Lista paginada de los sobres de la organización, con folio, estatus y conteos.

GET/envelopes/{id}envelopes:read

Estatus completo: participantes con su estado y fecha de firma, archivos con su huella SHA-256 y su constancia NOM-151, y la bitácora de eventos.

POST/envelopes/{id}/sendenvelopes:write

Envía a firma un sobre que quedó en borrador.

GET/envelopes/{id}/documents/{documentId}envelopes:read

Devuelve un enlace firmado (15 minutos) al PDF certificado con las firmas estampadas y la constancia NOM-151 en base64.

Webhooks firmados

Registra una URL HTTPS y suscríbete a los eventos que necesites. Cada entrega incluye X-Zign-Event, X-Zign-Timestamp y X-Zign-Signature. Valida la firma recalculando el HMAC-SHA256 de `${timestamp}.${cuerpo}` con tu secreto antes de procesar el evento.

const esperado = "sha256=" + crypto
  .createHmac("sha256", process.env.ZIGN_WEBHOOK_SECRET)
  .update(timestamp + "." + rawBody)
  .digest("hex");

Eventos: nom151.constancia.emitida, nom151.constancia.fallida, envelope.created, envelope.sent, envelope.signer_signed, envelope.completed, envelope.declined, envelope.expired, document.certified.

Anclaje blockchain

Cada huella certificada se agrega como hoja de un árbol Merkle diario cuya raíz se ancla en Bitcoin a través de OpenTimestamps. Cualquiera puede comprobar que un documento formó parte de ese conjunto sin revelar su contenido.

# Consultar el anclaje de una fecha (público)
GET https://zerozign.com/api/public/v1/blockchain/anchors/2026-08-31

# Verificar un archivo desde el navegador (el archivo nunca se sube)
https://zerozign.com/verificar-blockchain

Errores

{ "error": true, "code": "insufficient_credits", "message": "Sin certificados disponibles." }
HTTPcodeQué hacer
400invalid_hash / invalid_json / missing_inputCorrige la petición
401unauthorizedRevisa la llave
403forbidden_scopeAgrega el alcance a la llave
402insufficient_creditsCompra certificados en el backoffice
404not_foundFolio o huella inexistente
422psc_rejectedDatos rechazados por el PSC; no reintentes igual
429rate_limitedEspera y reintenta con retroceso exponencial
503psc_unavailableReintenta en unos minutos; el cobro se reversa

Checklist de integración

Nuestros certificados no tienen vigencia: se consumen al usarse y no caducan.

Volver al inicio