Integra la firma electrónica en tu stack
Envía sobres, sigue las firmas, recibe webhooks. API REST simple, OpenAPI 3.0, ejemplos curl/Node/Python — todo para conectar Certyneo con tu HRIS, CRM o software empresarial en pocas horas.
Inicio rápido
Tres pasos: crea una clave API desde la configuración, codifica tu PDF en base64, envía. La respuesta contiene el `signUrl` que puedes compartir directamente con el destinatario.
# 1. Upload the PDF (multipart) and capture the returned document id.
DOC_ID=$(curl -s -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf" | jq -r .id)
# 2. Create a DRAFT envelope referencing the uploaded document.
ENV_ID=$(curl -s -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d "{
\"subject\": \"Contrat de prestation\",
\"documentIds\": [\"$DOC_ID\"],
\"recipients\": [
{ \"email\": \"client@example.com\", \"name\": \"Marie Dubois\", \"role\": \"SIGNER\" }
]
}" | jq -r .id)
# 3. Dispatch the envelope — this sends the invitation email/SMS.
curl -X POST https://certyneo.com/api/v1/envelopes/$ENV_ID/send \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"// Plain fetch, no SDK to install.
const auth = { Authorization: `Bearer ${process.env.CERTYNEO_API_KEY}` };
// 1. Upload the PDF (multipart).
const fd = new FormData();
fd.append("file", new Blob([pdfBuffer], { type: "application/pdf" }), "contrat.pdf");
const doc = await fetch("https://certyneo.com/api/v1/documents", {
method: "POST", headers: auth, body: fd,
}).then((r) => r.json());
// 2. Create the DRAFT envelope.
const envelope = await fetch("https://certyneo.com/api/v1/envelopes", {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({
subject: "Contrat de prestation",
documentIds: [doc.id],
recipients: [
{ email: "client@example.com", name: "Marie Dubois", role: "SIGNER" },
],
}),
}).then((r) => r.json());
// 3. Dispatch — this triggers the invitation channel for every recipient.
await fetch(`https://certyneo.com/api/v1/envelopes/${envelope.id}/send`, {
method: "POST", headers: auth,
});
console.log(envelope.id);import os, requests
auth = {"Authorization": f"Bearer {os.environ['CERTYNEO_API_KEY']}"}
# 1. Upload the PDF (multipart).
with open("contrat.pdf", "rb") as f:
doc = requests.post(
"https://certyneo.com/api/v1/documents",
headers=auth,
files={"file": ("contrat.pdf", f, "application/pdf")},
).json()
# 2. Create the DRAFT envelope.
envelope = requests.post(
"https://certyneo.com/api/v1/envelopes",
headers={**auth, "Content-Type": "application/json"},
json={
"subject": "Contrat de prestation",
"documentIds": [doc["id"]],
"recipients": [
{"email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER"},
],
},
).json()
# 3. Dispatch — this triggers the invitation channel for every recipient.
requests.post(
f"https://certyneo.com/api/v1/envelopes/{envelope['id']}/send",
headers=auth,
)
print(envelope["id"])Pruebe la API desde sus herramientas
La colección Postman y la ficha RapidAPI se generan desde la especificación OpenAPI que también documenta esta página. Los tres permanecen alineados con la API real, endpoint por endpoint, en lugar de divergir en el primer añadido.
Colección Postman
Las 25 solicitudes organizadas por dominio — sobres, documentos, modelos, sellos, webhooks — con un ejemplo de cuerpo y respuesta para cada una. Pegue su clave en la variable apiKey de la colección, luego lance GET /health: no requiere autenticación y confirma que su configuración es correcta antes de la primera llamada autenticada.
Sobres
Creación, envío, seguimiento de estado, cancelación. Un sobre puede contener varios documentos y varios firmantes (en paralelo o secuencial).
Webhooks
Todos los eventos de sobre y destinatario (`envelope.sent`, `recipient.signed`, `envelope.completed`…) entregados en la URL de su elección — lista completa en /developers/webhooks. HMAC SHA-256 en cada carga útil para verificar el origen.
Autenticación simple
Bearer token. Una clave por entorno (test / prod). Revocable instantáneamente. Límite 100 req/min/clave, burst de 200, 429 limpio con encabezado Retry-After.
Puntos finales disponibles
Las 53 rutas públicas: cuenta, documentos, sobres, plantillas, webhooks, sellos electrónicos, claves API y facturación. Todas aceptan un token Bearer y devuelven JSON.
| Método | Ruta | Descripción |
|---|---|---|
| GET | /api/v1/account/me | Identidad del llamante autenticado (id, correo electrónico, plan) : prueba de identificadores sin alcance requerido |
| GET | /api/v1/sandbox | Contar los datos creados con las claves de prueba (eliminados automáticamente al cabo de 30 días) |
| DELETE | /api/v1/sandbox | Eliminar todos los datos creados con las claves de prueba, sin tocar los datos reales |
| POST | /api/v1/documents | Cargar un PDF (multiparte) : devuelve el id del documento |
| GET | /api/v1/documents | Listar los documentos |
| GET | /api/v1/documents/{id} | Leer los metadatos de un documento |
| DELETE | /api/v1/documents/{id} | Eliminar un documento |
| GET | /api/v1/envelopes | Listar los sobres (filtrar con ?status= y ?limit=) |
| POST | /api/v1/envelopes | Crear un sobre (estado DRAFT) : a partir de un templateId, o de documentIds con una matriz fields opcional |
| GET | /api/v1/envelopes/{id} | Leer el estado de un sobre |
| PATCH | /api/v1/envelopes/{id} | Modificar un sobre DRAFT |
| DELETE | /api/v1/envelopes/{id} | Eliminar un sobre DRAFT (409 una vez enviado : cancelarlo en su lugar) |
| POST | /api/v1/envelopes/{id}/send | Enviar un sobre DRAFT : remite las invitaciones |
| POST | /api/v1/envelopes/{id}/void | Cancelar un sobre enviado no completamente firmado aún : los firmantes en espera son notificados |
| POST | /api/v1/envelopes/{id}/remind | Recordar bajo demanda a los firmantes en espera de un sobre enviado (un destinatario específico opcional) |
| GET | /api/v1/envelopes/{id}/audit-trail | Descargar el PDF del diario de prueba eIDAS |
| POST | /api/v1/envelopes/{id}/embed-url | Devuelve la URL de firma de un destinatario, acompañada de una autorización de marco para el origen solicitado. Para llamar en el momento del clic: la autorización es válida por dos horas. |
| GET | /api/v1/audit-anchors/{root} | Público : metadatos de un lote de auditoría anclado, o archivo de prueba .ots con ?format=ots (sin autenticación) |
| POST | /api/v1/audit-anchors/verify | Público : verificar una entrada de auditoría y su prueba frente a la raíz de Merkle anclada (sin autenticación, no revela nada) |
| GET | /api/v1/envelopes/{id}/signed-document | Descargar el PDF firmado (una vez COMPLETED) |
| GET | /api/v1/envelopes/bulk | Listar sus envíos en masa |
| POST | /api/v1/envelopes/bulk | Envío masivo: crear N sobres a partir de una plantilla y un CSV (solo Standard/Business) |
| GET | /api/v1/envelopes/bulk/{id} | Progreso de un envío masivo: contadores, fallos por línea, sobres creados |
| GET | /api/v1/templates | Listar plantillas de sobre reutilizables |
| POST | /api/v1/templates | Crear una plantilla (documentos, roles, campos posicionados) |
| GET | /api/v1/workspaces | Enumerar los espacios de trabajo en los que puede crear un sobre |
| POST | /api/v1/sepa-mandates | Generar el PDF de un mandato SEPA y su sobre DRAFT, campos ya colocados |
| POST | /api/v1/payroll-adapters/normalize | Normalizar un CSV de nómina (Silae, Sage Paie, PayFit, Lucca) al formato de envío masivo |
| POST | /api/v1/ag-copropriete | Crear un sobre de asamblea general de comunidad de propietarios (resoluciones y participaciones) |
| POST | /api/v1/ag-copropriete/{envelopeId}/votes | Registrar los votos de un propietario sobre las resoluciones de la asamblea |
| POST | /api/v1/ag-copropriete/{envelopeId}/tally | Escrutinio de la asamblea: resultado por resolución, ponderado por las participaciones |
| GET | /api/v1/videos/{videoId} | Descargar un vídeo de identidad conservado: derecho de acceso RGPD (art. 15) |
| GET | /api/v1/webhooks | Listar los webhooks |
| POST | /api/v1/webhooks | Registrar un webhook: devuelve el secreto de firma una sola vez |
| GET | /api/v1/webhooks/{id} | Leer una suscripción webhook |
| PATCH | /api/v1/webhooks/{id} | Modificar la URL, los eventos o el estado activo |
| DELETE | /api/v1/webhooks/{id} | Cancelar la suscripción del webhook |
| POST | /api/v1/seals | Aplicar un sello electrónico cualificado en un documento |
| GET | /api/v1/seals/{id} | Leer el estado de un sello |
| GET | /api/v1/seals/{id}/certificate | Descargar el certificado del sello |
| GET | /api/v1/payslips/workspaces | Nóminas: los espacios para los que esta clave distribuye, poseídos o delegados por un cliente (despachos contables, gestores de nómina) |
| GET | /api/v1/payslips/employees | Nóminas: el registro de los empleados, incluyendo quienes han rechazado la remisión electrónica (nómina en papel debida) |
| PUT | /api/v1/payslips/employees | Nóminas: agregar o actualizar empleados del registro (nunca los elimina) |
| POST | /api/v1/payslips | Entregar una nómina (PDF) en la caja fuerte de un empleado: sellada, conservada 50 años, reintentos sin duplicados |
| GET | /api/v1/payslips | Listar las nóminas entregadas, con su prueba de consulta |
| GET | /api/v1/keys | Listar las claves de API |
| POST | /api/v1/keys | Crear una clave de API: el secreto se muestra solo una vez |
| PATCH | /api/v1/keys/{id} | Renombrar o revocar una clave |
| DELETE | /api/v1/keys/{id} | Eliminar una clave |
| GET | /api/v1/billing/usage | Consumo del período actual y costo proyectado |
| GET | /api/v1/status | Estado del servicio |
| GET | /api/v1/health | Verificación de salud: base de datos, cola de espera y almacenamiento de objetos |
| GET | /api/v1/openapi | Especificación OpenAPI legible por máquina |
Plantillas de sobre
Una plantilla registra de una vez por todas el PDF, los roles y la ubicación de los campos de firma, luego se reutiliza en cada envío: pase su identificador en templateId en lugar de documentIds, y los campos posicionados se copian en el sobre creado.
- • Las plantillas se crean desde el panel de control (Plantillas → Nueva plantilla), donde deposita el documento y posiciona los campos con el ratón — este es el camino más simple. La API también permite crearlas mediante POST /api/v1/templates, proporcionando los documentos, los roles y los campos; tenga en cuenta que los campos se posicionan con coordenadas absolutas (página, x, y, ancho, alto), por lo que debe conocer la maquetación del PDF.
- • En una cuenta que aún no ha registrado ninguna plantilla, GET /api/v1/templates devuelve una lista vacía. Este es el comportamiento normal, no un defecto de autenticación.
- • La lista contiene solo las plantillas que pertenecen al usuario propietario de la clave API. Una plantilla creada por un colega no aparece, ni siquiera dentro de un espacio de trabajo compartido: genere la clave desde la cuenta que posee la plantilla.
- • templateId y documentIds se excluyen mutuamente: envíe uno u otro, nunca ambos ni ninguno.
- • Proporcione al menos tantos destinatarios SIGNER como roles de firmantes tenga la plantilla, de lo contrario la creación se rechaza con un 400. El campo signerCount devuelto por la lista indica el número esperado.
- • El nivel de firma de la plantilla se hereda por el sobre, a menos que la solicitud pase explícitamente signatureLevel.
# 1. Discover the templates saved on this account.
curl -s https://certyneo.com/api/v1/templates \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
# {
# "data": [
# { "id": "cmdq7f4k80001s6y2h1xa9pl3", "name": "Contrat de prestation",
# "signerCount": 2, "documentCount": 1, "signatureLevel": "SIMPLE" }
# ],
# "pagination": { "page": 1, "pageSize": 20, "total": 1, "pages": 1 }
# }
#
# An empty "data" array means no template exists on this account yet —
# create one from the dashboard, it is not an authentication problem.
# 2. Create the envelope FROM the template: no documentIds and no field
# coordinates, both are carried by the template. Pass one SIGNER
# recipient per signer role, in the template's role order.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"templateId": "cmdq7f4k80001s6y2h1xa9pl3",
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" },
{ "email": "legal@example.com", "name": "Paul Martin", "role": "SIGNER" }
]
}'
# 3. The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.Desde Power Automate o Zapier
La acción « Crear un sobre » de nuestros conectores sin código solo cubre la ruta por plantilla: el campo Plantilla es obligatorio. Para un documento ad hoc que cambia en cada ejecución, utilice la acción « Cargar un documento » seguida de una acción HTTP bruta hacia POST /api/v1/envelopes pasando el documentIds retornado.
Envío del documento: dos formas aceptadas
POST /api/v1/documents acepta el archivo de dos formas, a su elección. Los mismos controles se aplican en ambos casos: tipos permitidos, límite de 50 Mo, verificación de firma binaria y análisis antivirus.
- • En multipart/form-data, con una parte denominada file. Esta es la forma clásica, la de curl -F y de la mayoría de las bibliotecas.
- • En cuerpo bruto: los bytes del archivo constituyen el cuerpo de la solicitud, y el encabezado Content-Type proporciona su tipo (application/pdf por ejemplo). Útil desde una herramienta que transmite el contenido tal cual, sin envolver la solicitud — esto es lo que hace el conector Power Automate.
- • En cuerpo bruto, el nombre del archivo no tiene lugar en el cuerpo: indíquelo a través del encabezado X-File-Name o el parámetro ?fileName=. Sin él, el documento se nombra según su tipo.
- • Un tipo no soportado responde 415 nombrando las dos formas aceptadas, y un cuerpo anunciado como multipart pero ilegible responde 400. Ninguno de los dos es un error de servidor.
# a. multipart/form-data — the classic shape.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf;type=application/pdf"
# b. raw body — the file bytes ARE the body, typed by Content-Type.
# The filename has nowhere to live in the body, so pass it as a header
# (or ?fileName=). Without it the document is named after its type.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/pdf" \
-H "X-File-Name: contrat.pdf" \
--data-binary "@contrat.pdf"
# Both return the same 201 with the document id to pass as documentIds.Colocación de campos de firma
Sin plantilla, un sobre creado a partir de documentIds no tiene ningún campo preposicionado: el firmante recibe el documento sin ubicación para firmar. La matriz fields, transmitida en la misma llamada de creación, coloca cada campo al punto exacto — es el equivalente, en el lado de la API, de lo que una plantilla registra de una vez por todas.
- • Las coordenadas están en puntos PDF, origen en la esquina superior izquierda de la página y eje Y hacia abajo (una página A4 mide 595 × 842 puntos). x e y designan la esquina superior izquierda del campo, width y height su tamaño.
- • pageNumber comienza en 1, documentIndex comienza en 0. Un número de página más allá del documento no se rechaza en la creación: el campo se ignora en el momento de la firma y no aparece en ninguna parte — es lo primero que hay que verificar cuando falta un campo en la llamada.
- • recipientEmail debe corresponder a uno de los destinatarios de la misma llamada, sin distinción de mayúsculas y minúsculas. De lo contrario, la creación falla enumerando todas las líneas defectuosas, lo que evita corregirlas una por una.
- • fields y templateId se excluyen mutuamente: una plantilla ya lleva su propio diseño. Por lo tanto, la matriz fields solo se utiliza con documentIds.
- • Tipos aceptados: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX y RADIO_GROUP. required es verdadero por defecto; placeholder y dateFormat son opcionales, y options solo se retiene para RADIO_GROUP.
- • Un sobre acepta un máximo de 100 campos, 20 documentos y 50 destinatarios — los límites de su plan pudiendo ser inferiores.
# Ad-hoc envelope WITH pre-placed fields — no template involved.
# Coordinates are PDF points, origin TOP-LEFT of the page, +Y downwards
# (A4 = 595 x 842 pt). x / y are the field box's top-left corner.
#
# The last field is positioned by ANCHOR instead of by eye: the server
# locates "Signature du client" in the PDF and computes the spot. x / y
# stay required there — they are the fallback if the text is not found.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"documentIds": ["cmdq7f4k80001s6y2h1xa9pl3"],
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" }
],
"fields": [
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"x": 90, "y": 640, "width": 180, "height": 44 },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "DATE_SIGNED",
"x": 320, "y": 640, "width": 140, "height": 30,
"dateFormat": "DD/MM/YYYY" },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "TEXT",
"x": 90, "y": 700, "width": 200, "height": 30,
"placeholder": "Fonction", "required": false },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"anchorText": "Signature du client", "anchorPlacement": "below",
"anchorIndex": 0,
"x": 90, "y": 640, "width": 180, "height": 44 }
]
}'
# The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.Anclas de texto: colocar un campo sin conocer las coordenadas
En lugar de coordenadas, un campo puede citar un texto impreso en el documento: anchorText lo localiza en el PDF y el servidor calcula la posición en la creación. Este es el modo a privilegiar cuando el documento se regenera en cada envío — combinación de correspondencia, generador de contratos — porque el diseño cambia mientras que la mención "Firma del cliente" permanece. anchorPlacement indica de qué lado del texto se coloca el campo (right por defecto, si no below, above o left) y anchorIndex elige la ocurrencia cuando el texto aparece varias veces.
x e y siguen siendo obligatorios incluso con un ancla: sirven como respaldo. Un ancla no encontrada no hace fallar la creación — el campo mantiene la posición literal que proporcionó, sin error ni advertencia en la respuesta. Indique por lo tanto un respaldo plausible en lugar de 0,0, y verifique el resultado en un primer envío.
Firma integrada: firmar sin salir de su aplicación
Su cliente consulta y firma su documento desde su propia interfaz. La ceremonia se abre en una ventana sobre su página y vuelve a usted automáticamente una vez finalizada. Del lado del servidor, nada nuevo: crea el sobre como de costumbre proporcionando redirectUrl, luego confía al SDK la URL de firma del destinatario.
- • Llame a Certyneo.sign() directamente en su controlador de clic y pase su llamada de servidor por getUrl. Un await antes de sign() sale del gesto del usuario: Safari y Firefox bloquean la ventana. El SDK la abre de inmediato y la carga cuando su promesa se resuelve.
- • redirectUrl es el canal de retorno. Le devolvemos el firmante añadiendo certyneo_status (completed o declined) y certyneo_envelope. Cargue el mismo script en esta página de retorno: es el que avisa a la ventana del portal que quedó abierta atrás.
- • En modo integrado, nuestros propios llamados a la acción se suprimen. Su cliente nunca ve una invitación para crear una cuenta Certyneo.
- • Si el navegador rechaza la ventana, el SDK cambia automáticamente a redirección de página completa. El recorrido es idéntico para el firmante y su página de retorno recibe exactamente los mismos parámetros.
- • Intencionalmente no existe un callback «el usuario abandonó»: el estado de la ventana no es legible desde su página, y un callback así se dispararía erróneamente. Una firma que no llega permanece en espera hasta el webhook.
// 1. Your server creates and sends the envelope, then hands the browser the
// recipient's signing URL. Nothing new on the API side:
// POST /api/v1/envelopes { …, "redirectUrl": "https://your-app.com/quote/42/signed" }
// POST /api/v1/envelopes/{id}/send → recipients[].accessToken
// signingUrl = "https://certyneo.com/sign/" + accessToken
// 2. On your quote page — load the SDK once:
// <script src="https://certyneo.com/embed.js"></script>
document.querySelector("#sign").addEventListener("click", () => {
Certyneo.sign({
// Called AFTER the window is already open, so no popup blocker ever
// sees a delay between the click and window.open.
getUrl: () =>
fetch("/api/quote/42/signature", { method: "POST" })
.then((r) => r.json())
.then((d) => d.signingUrl),
onCompleted: (e) => showConfirmation(e.envelopeId),
onDeclined: () => showDeclined(),
onError: (e) => showError(e),
});
});
// 3. On https://your-app.com/quote/42/signed — your return page — load the
// same script and render a short confirmation. It relays the outcome to
// the portal window behind it, then closes itself.El evento del navegador no es una prueba de firma
onCompleted es una señal de visualización, emitida por un navegador, por lo tanto falsificable por cualquiera desde su consola. Nunca cambie un expediente a «firmado» sobre esta base: úselo para refrescar la pantalla, y confíe en el webhook envelope.completed firmado recibido por su servidor para el estado real. Es la trampa clásica de las integraciones de pago, y se reproduce idénticamente aquí.
Desarrollar en su puesto
Con una clave de prueba, redirectUrl acepta http://localhost (y 127.0.0.1): monta todo el recorrido en su máquina antes de desplegar. Una clave real lo rechaza, para que ningún sobre de producción devuelva un verdadero firmante a una máquina que no es la suya.
Mostrar la ceremonia en su página
El modo marco muestra la firma dentro de su interfaz, sin ventana. Requiere un paso más que el modo ventana: probar que el sitio que la mostrará le pertenece. Esto es lo que impide que un tercero encuadre nuestras ceremonias para engañar a sus clientes.
- • Declare su sitio en Configuración → Firma integrada, luego publique el registro DNS indicado. Una dirección exacta: un subdominio o un puerto diferente cuenta como otro sitio.
- • En cada firma, solicite una URL fresca a POST /api/v1/envelopes/{id}/embed-url. Lleva la autorización de visualización y es válida durante dos horas, lo que corresponde al momento del clic, no a la creación del sobre.
- • Dos recorridos no pueden llevarse a cabo en un marco: la firma cualificada, cuya verificación de identidad se niega a ser encuadrada a su vez, y el pago en la firma. En ambos casos, el firmante se orienta hacia una ventana completa.
- • La mención «Impulsado por Certyneo» desaparece del marco a partir del plan Business. El modo marco en sí está incluido desde el plan Standard.
// Mode cadre : la cérémonie s'affiche DANS votre page.
//
// 1. Déclarez votre site une fois pour toutes dans Réglages → Signature
// intégrée, et publiez l'enregistrement DNS qu'on vous y donne.
//
// 2. À chaque signature, votre serveur demande une URL fraîche. Elle porte
// l'autorisation qui permet au navigateur d'afficher la cérémonie chez
// vous, et vaut deux heures :
//
// POST /api/v1/envelopes/{id}/embed-url
// { "origin": "https://portail.exemple.fr" }
// -> { "signingUrl": "…", "expiresAt": "…" }
Certyneo.sign({
mode: "iframe",
el: "#zone-signature", // sélecteur ou nœud de votre page
getUrl: () =>
fetch("/api/devis/42/signature", { method: "POST" })
.then((r) => r.json())
.then((d) => d.signingUrl),
onCompleted: (e) => afficherConfirmation(e.envelopeId),
onDeclined: () => afficherRefus(),
});
// Le cadre parle à votre page par postMessage — pas besoin de page de retour,
// contrairement au mode fenêtre.Hacer firmar sin que ningún correo electrónico se envíe
Un portal que muestra la ceremonia en él a menudo no necesita nuestra invitación: llega junto a su propio recorrido y propone una cuenta a un cliente que no la desea. Asigne el valor NONE al canal de notificación de un destinatario y no se le enviará nada más — es usted quien lo lleva a su firma.
- • La configuración es por destinatario, no por sobre: puede silenciar al cliente que aloja y conservar el correo electrónico para un cofirmante externo, quien no tiene portal.
- • Está reservado a los firmantes y aprobadores, los únicos a quienes tiene un enlace que remitir. Lo lee en la respuesta de creación y envío, o solicita una URL nueva al hacer clic en POST /api/v1/envelopes/{id}/embed-url.
- • Los recordatorios automáticos se detienen por sí solos para este destinatario: nunca le escribimos, no empezamos con un recordatorio. Los otros destinatarios continúan siendo recordados normalmente.
- • El certificado de firma lo menciona, destinatario por destinatario. Un expediente de prueba que guardara silencio al respecto permitiría creer que este firmante recibió de nosotros una invitación que nunca existió.
POST /api/v1/envelopes
{
"subject": "Mandat de gestion",
"documentIds": ["doc_8f2c1a4b9e7d"],
"recipients": [
{
"email": "client@exemple.fr",
"name": "Camille Client",
"role": "SIGNER",
"notificationChannel": "NONE"
},
{
"email": "notaire@exemple.fr",
"name": "Maître Notaire",
"role": "SIGNER"
}
]
}
// La réponse rend le lien de chaque signataire :
//
// "recipients": [
// { "email": "client@exemple.fr", "accessToken": "…",
// "notificationChannel": "NONE" },
// { "email": "notaire@exemple.fr", "accessToken": "…",
// "notificationChannel": "EMAIL" }
// ]
//
// Le client ne reçoit rien : vous l'emmenez sur sa signature depuis votre
// portail. Le notaire, lui, reçoit son invitation comme d'habitude.Mostrar el nombre de su cliente como remitente
Por defecto, el firmante lee el nombre del titular de la clave API. Si hace firmar documentos de varias empresas con una sola clave, pase el campo sender a la creación del sobre: la página de firma y los correos electrónicos de invitación y recordatorio muestran entonces el nombre de la empresa correspondiente.
- • Reservado para el plan Business y superiores. En un plan inferior, la creación se rechaza en lugar de permitir que el firmante lea un nombre diferente al esperado.
- • El nombre es una pantalla: el certificado y la pista de auditoría conservan el remitente real, y los correos electrónicos siempre provienen de Certyneo.
- • La dirección es opcional. Sin ella, el firmante solo ve el nombre, nunca la dirección del titular de la clave.
POST /api/v1/envelopes
{
"subject": "Devis 2026-118",
"documentIds": ["doc_8f2c1a4b9e7d"],
"recipients": [
{ "email": "client@exemple.fr", "name": "Camille Client", "role": "SIGNER" }
],
"sender": {
"name": "1.2.3. Panneaux Solaires",
"email": "devis@123-panneaux-solaires.fr"
}
}Autenticación
Cada llamada lleva una clave API en el encabezado Authorization. Las claves se generan desde Configuración → Claves API y solo se muestran una vez.
GET /api/v1/account/me HTTP/1.1Host: certyneo.com
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
# 200 OK
{ "data": { "id": "usr_…", "email": "you@example.com", "plan": "BUSINESS", "environment": "live" } }- • Formato: sk_live_… en producción, sk_test_… para la zona de pruebas. Encabezado: Authorization: Bearer <clé>.
- • Alcances: envelopes, documents, webhooks, seals — en lectura (:read) o escritura (:write). La escritura implica la lectura; el alcance * otorga todos los derechos.
- • Las claves sk_test_ crean recursos en el entorno de pruebas, excluidos de la cuota y la facturación. No se envía ningún correo real al destinatario, a menos que su dirección coincida con el correo de la cuenta que envía — útil para probar el flujo completo contigo mismo.
- • Errores: 401 clave inválida, 403 alcance insuficiente, 429 límite de velocidad excedido, 402 cuota mensual alcanzada.
Forma de las respuestas
Un punto a conocer antes de escribir tu cliente: las colecciones se encapsulan en un objeto data, mientras que los recursos unitarios se devuelven planos. Leer response.data.data en un recurso unitario devuelve por lo tanto undefined.
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
"data": [
{ "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
]
}// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
"id": "env_abc123",
"subject": "Contrat",
"status": "COMPLETED",
"recipients": [ /* … */ ]
}Límites de velocidad
Los límites garantizan una calidad de servicio estable para todos los clientes. Si necesitas más, contáctanos.
- • 100 solicitudes por minuto por clave API
- • Burst tolerado hasta 200 solicitudes en menos de 10s
- • Respuesta 429 con encabezado Retry-After indicando el retraso en segundos