Constancias
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_…").
El objeto ConstanciaResponse
Atributos
-
livemodeboolean requeridotrueen entornolive,falseentest/dev(marca de agua, sin validez legal). -
idstring requerido -
hashSha256string requerido -
externalIdstring requerido puede ser null -
labelstring requerido puede ser null -
constanciastring requerido -
constanciaEncodingstring, siempre "base64" -
constanciaMediaTypestring -
constanciaSha256string requerido -
serialNumberstring requerido puede ser null -
algorithmstring requerido puede ser null -
issuerstring requerido puede ser null -
sealedAtstring (fecha-hora ISO 8601) requerido puede ser null -
policyOidstring requerido puede ser null -
tsaNamestring requerido puede ser null -
environmentstring requerido -
sandboxboolean requerido -
downloadUrlstring requerido -
downloadUrlExpiresAtstring (fecha-hora ISO 8601) requerido -
createdAtstring (fecha-hora ISO 8601) requerido
Emitir constancia NOM-151
POST /constancias
Emite una Constancia de Conservación NOM-151 a partir del hash SHA-256 de tu documento. Tu documento nunca sale de tu infraestructura.
No es una restricción nuestra: la NOM-151-SCFI-2016 lo ordena. Apéndice Normativo A, numeral A.2.4 — «el Prestador de Servicios de Certificación únicamente recibirá la huella digital electrónica del mensaje de datos». Usa este endpoint si ya firmas por tu cuenta (e.firma del SAT, tu propio flujo) y solo necesitas la prueba legal del momento en que el documento existió.
El hash va en hexadecimal minúsculas de 64 caracteres — exactamente lo que produce sha256sum archivo.pdf. Se aceptan mayúsculas y se normalizan; no se acepta base64 ni prefijos tipo sha256:.
Idempotency-Key es obligatoria. Este endpoint cobra y llama a un PSC externo: sin la key, un timeout de red te deja sin forma segura de reintentar. Reintentar con la misma key devuelve la primera respuesta, nunca emite dos veces.
externalId es tu propia referencia (el folio de tu expediente). Te sirve para recuperar la constancia después sin haber guardado nuestro id, y como segunda red contra el doble cobro. Reusar un externalId con el mismo hash devuelve la constancia ya emitida; reusarlo con otro hash devuelve 409 — la referencia ya está tomada por otro documento, y devolverte la constancia equivocada sería peor que fallar.
Facturación y entornos. En live consume créditos y llama al PSC. Con una API key test o dev no cobra, no contacta al PSC y devuelve un artefacto sin validez legal, marcado con sandbox: true y livemode: false.
Requiere contrato. El addon se activa por tenant tras firmar el contrato de prestación de servicio; sin él, live responde 403 CONTRACT_REQUIRED.
Parámetros
-
Idempotency-Keystring header requeridoClave única (UUID v4) que vuelve idempotente el POST: un reintento con la misma clave repite la respuesta original en lugar de volver a crear, cobrar o notificar.
-
AllSign-Versionenum headerFecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400
UNSUPPORTED_API_VERSION.Valores:
2026-07-11
Cuerpo de la petición
-
hashSha256string requeridoSHA-256 hex del documento.
-
externalIdstring puede ser null -
labelstring puede ser null
Devuelve
201 Constancia emitida. El artefacto viene inline en base64 en constancia. — el objeto ConstanciaResponse
Recuperar una constancia
GET /constancias/{constancia_id}
Devuelve una constancia que emitimos, con el artefacto inline en base64 — así que basta con haber guardado el id (o tu externalId) para recuperarla meses después.
Archiva constancia, no downloadUrl. La URL de descarga es una conveniencia con caducidad (downloadUrlExpiresAt); si guardas el JSON con la URL y vuelves después, te queda un enlace muerto. El base64 es la fuente de verdad y no expira.
Los campos sealedAt, serialNumber, policyOid y tsaName se extraen del interior del token, donde están cubiertos por la firma — no del JSON que envuelve la respuesta del PSC. sealedAt es el genTime del sello: el instante con valor legal.
Con Accept: application/pkcs7-mime la misma ruta devuelve el DER crudo en vez del JSON, listo para pasárselo a openssl sin decodificar nada.
Parámetros
-
constancia_idstring ruta requerido -
AllSign-Versionenum headerFecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400
UNSUPPORTED_API_VERSION.Valores:
2026-07-11
Devuelve
200 La constancia, con el artefacto inline. — el objeto ConstanciaResponse
Listar constancias
GET /constancias
Lista las constancias del tenant, más recientes primero, con paginación por cursor.
El listado NO trae el artefacto. Devolver el base64 de hasta 100 constancias por página significaría descargarlas todas de nuestro almacenamiento en cada petición. Para el artefacto usa GET /v3/constancias/{constanciaId}, que trae uno.
Sirve para conciliar: filtra por tu externalId para encontrar el expediente que buscas, o pagina el periodo completo para cuadrar lo emitido contra lo cobrado.
Paginación: manda startingAfter con el nextCursor de la respuesta anterior. hasMore te dice si vale la pena pedir otra página.
El listado está acotado al entorno de tu API key: una key test no ve las constancias live del tenant, ni al revés.
Parámetros
-
limitinteger query -
startingAfterstring query -
externalIdstring query -
AllSign-Versionenum headerFecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400
UNSUPPORTED_API_VERSION.Valores:
2026-07-11
Devuelve
200 Página de constancias (sin el artefacto — ver la nota arriba).
Ver los 5 atributos de la respuesta
-
objectstring, siempre "list"Siempre
"list". -
dataarray de objetos requeridoVer 14 atributos hijos
-
data[].livemodeboolean requeridotrueen entornolive,falseentest/dev(marca de agua, sin validez legal). -
data[].objectstring, siempre "constancia"Siempre
"constancia". -
data[].idstring requerido -
data[].hashSha256string requerido -
data[].externalIdstring puede ser null -
data[].labelstring puede ser null -
data[].constanciaSha256string puede ser null -
data[].serialNumberstring puede ser null -
data[].sealedAtstring (fecha-hora ISO 8601) puede ser null -
data[].policyOidstring puede ser null -
data[].tsaNamestring puede ser null -
data[].environmentstring requerido -
data[].sandboxboolean requerido -
data[].createdAtstring (fecha-hora ISO 8601) requerido
-
-
hasMoreboolean requerido -
limitinteger requerido -
nextCursorstring puede ser null
Verificar una constancia
POST /constancias/verify
Corre los cuatro checks criptográficos sobre una constancia y devuelve el resultado por criterio.
| Check | Qué prueba |
|---|---|
| integrity | El hash sellado dentro del token es el de tu documento |
| chainOfTrust | El certificado firmante encadena a la raíz de Secretaría de Economía |
| cmsSignature | La firma CMS del token es válida (RFC 5652) |
| certValidity | El certificado estaba vigente al momento del sellado |
Los cuatro son necesarios y ninguno implica a otro: un imprint correcto no dice nada de quién firmó, y una firma válida de un emisor cualquiera no acredita nada.
status es tri-estado, no un booleano (ETSI EN 319 102-1):
- VALID — los cuatro checks pasaron.
- INVALID — afirmación fuerte: el artefacto está mal (el documento no es el que se selló, o el emisor no es acreditado).
- INDETERMINATE — no pudimos concluir. Token ilegible, o un check que no se pudo completar. No significa que la constancia sea falsa.
Esa distinción importa: colapsar INDETERMINATE en INVALID te haría reportar «tu constancia es falsa» cuando el problema es de nuestro lado.
> Esto es una conveniencia, no una autoridad. AllSign no es PSC acreditado, y preguntarle al emisor si su propio artefacto es válido no constituye prueba ante un tercero. Para eso está la verificación independiente: baja la raíz en /v3/constancias/certchain y verifica con openssl por tu cuenta. El valor de este endpoint es que valida el certificado del PSC contra la raíz correcta, que es el paso que se suele equivocar.
Puedes mandar constancia (base64) + hashSha256, o solo constanciaId si la emitimos nosotros — en ese caso el hash sale de nuestro registro.
Parámetros
-
AllSign-Versionenum headerFecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400
UNSUPPORTED_API_VERSION.Valores:
2026-07-11
Cuerpo de la petición
-
hashSha256string puede ser null -
constanciastring puede ser null -
constanciaIdstring puede ser null
Devuelve
200 Resultado de la verificación. Revisa status y checks; un INDETERMINATE con errors te dice qué no se pudo comprobar.
Ver los 12 atributos de la respuesta
-
statusenum requeridoValores:
VALIDINDETERMINATEINVALID -
reasonstring requerido -
hashSha256string puede ser null -
checksobjeto puede ser nullResultado POR CRITERIO. Los cuatro checks son independientes. Se publican por separado a propósito: un
INVALIDsin desglose no le dice al cliente si el documento fue alterado (integridad) o si el emisor no está acreditado (cadena) — son problemas distintos con remedios distintos.Ver 4 atributos hijos
-
checks.integrityboolean requerido -
checks.chainOfTrustboolean requerido -
checks.cmsSignatureboolean requerido -
checks.certValidityboolean requerido
-
-
sealedHashstring puede ser null -
sealedAtstring puede ser null -
serialNumberstring puede ser null -
policyOidstring puede ser null -
tsaNamestring puede ser null -
signerSubjectstring puede ser null -
signerIssuerstring puede ser null -
errorsarray de string
Raíz de confianza para verificar offline
GET /constancias/certchain
Devuelve en PEM el certificado raíz de la Autoridad Certificadora Raíz Segunda de Secretaría de Economía — el -CAfile que necesitas para verificar una constancia sin depender de AllSign.
⚠️ openssl ts -verify rechaza una constancia NOM-151 con la invocación normal. No es que la constancia esté mal: el certificado firmante no lleva el Extended Key Usage Time Stamping (solo Digital Signature, Non Repudiation), porque una constancia de conservación no es un sello de tiempo puro. Sin el flag correcto verás unsuitable certificate purpose y concluirás, equivocadamente, que la constancia es inválida.
El flag es -purpose any. Y como SeguriData entrega un token CMS pelado (no un TimeStampResp), hace falta además -token_in.
Si tu versión de openssl aun así se niega, openssl cms -verify -purpose any comprueba firma y cadena — pero no compara el message imprint, así que en ese camino tienes que extraer el TSTInfo y comparar el hash tú mismo.
> Servimos esta raíz por conveniencia, no como autoridad: no somos PSC acreditado. La fuente autoritativa es la Secretaría de Economía; si tu proceso requiere rigor, bájala de ahí y compara. El archivo que servimos se valida contra su fingerprint SHA-256 antes de entregarse.
Parámetros
-
AllSign-Versionenum headerFecha del contrato contra la que quieres resolver la petición. Si la omites se sirve la versión vigente; una fecha desconocida responde 400
UNSUPPORTED_API_VERSION.Valores:
2026-07-11
Devuelve
200 El certificado raíz en PEM.