Skip to content
DocuFirma
Included in the Pro plan

Developers

DocuFirma API

Bring advanced electronic signatures with a qualified timestamp into your software: create envelopes, track their status, download the signed documents and get notified by webhook.

Introduction

The API is REST, uses JSON for requests and responses, and is available to accounts with an active Pro plan. It uses your account's signatures and SMS, just like the web app.

Base URL: https://docufirma.es/api/v1

Authentication

Create a key in Settings → API and webhooks. It is shown only once: keep it in your secrets manager. Send it in the Authorization header with every request. You can have up to 5 active keys and revoke them at any time.

curl https://docufirma.es/api/v1/account \
  -H "Authorization: Bearer df_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

First envelope in one call

Create the envelope with its signers and a base64 document (up to 3 MB) and send it at once with send: true. The response includes each signer's status and the verification code.

POST /envelopes
curl https://docufirma.es/api/v1/envelopes \
  -H "Authorization: Bearer $DOCUFIRMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Contrato de servicios",
    "message": "Hola Lucía, aquí tienes el contrato.",
    "locale": "es",
    "signers": [
      { "first_name": "Lucía", "last_name": "Gómez", "email": "lucia@example.com" }
    ],
    "documents": [
      { "name": "contrato.pdf", "content_base64": "'"$(base64 -w0 contrato.pdf)"'" }
    ],
    "send": true
  }'
201 Created
{
  "id": "6c36f47e-86d5-4693-b4f5-c5da17f37621",
  "object": "envelope",
  "status": "sent",
  "title": "Contrato de servicios",
  "verification_code": "DF-7K2M-9QXA",
  "sent_at": "2026-11-03T10:15:02Z",
  "expires_at": "2026-12-03T10:15:02Z",
  "signers": [
    { "id": "…", "object": "signer", "email": "lucia@example.com", "status": "sent", … }
  ],
  "documents": [
    { "id": "…", "object": "document", "name": "contrato.pdf", "page_count": 3, "sha256": "…" }
  ]
}

Large documents

For files up to 25 MB, request an upload URL, send the file with PUT and complete the upload. DocuFirma validates the PDF (or converts the image) and computes its SHA-256 fingerprint.

# 1. Upload slot (valid for 2 hours)
curl -X POST https://docufirma.es/api/v1/envelopes/$ENVELOPE_ID/uploads \
  -H "Authorization: Bearer $DOCUFIRMA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "anexo.pdf", "size_bytes": 8421337 }'
# → { "id": "<upload_id>", "upload_url": "https://…", "method": "PUT", … }

# 2. Send the file
curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @anexo.pdf

# 3. Complete
curl -X POST https://docufirma.es/api/v1/envelopes/$ENVELOPE_ID/uploads/$UPLOAD_ID/complete \
  -H "Authorization: Bearer $DOCUFIRMA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "anexo.pdf" }'

# 4. Send the envelope
curl -X POST https://docufirma.es/api/v1/envelopes/$ENVELOPE_ID/send -H "Authorization: Bearer $DOCUFIRMA_API_KEY"

Endpoints

MethodPathDescription
GET/accountYour account: plan, signatures and SMS available.
GET/envelopesEnvelopes, newest first. Filter by status and paginate with limit and starting_after.
POST/envelopesCreates a draft envelope with optional signers and documents; with send: true it is sent right away.
GET/envelopes/{id}Envelope detail with signers and documents.
PATCH/envelopes/{id}Updates a draft. signers replaces the whole list.
DELETE/envelopes/{id}Deletes a draft and its documents.
POST/envelopes/{id}/documentsAdds a base64 document (up to 3 MB) to a draft.
POST/envelopes/{id}/uploadsReturns a signed URL to upload a large file with PUT.
POST/envelopes/{id}/uploads/{upload_id}/completeValidates the uploaded file and adds it to the draft.
POST/envelopes/{id}/sendSends the draft: reserves signatures and notifies the signers.
POST/envelopes/{id}/cancelCancels a pending envelope and returns its reserved signatures.
POST/envelopes/{id}/remindNotifies pending signers again (at most once per hour).
GET/envelopes/{id}/filesTemporary download URLs (5 min): originals and, once completed, signed PDFs, evidence certificate and timestamps.
GET/envelopes/{id}/eventsFull timeline of the envelope.
POST/envelopes/{id}/signers/{signer_id}/signing-urlSigning link for an in-person signer.

Statuses

An envelope goes draft → sent → viewed → completed, or ends as declined, expired or canceled. Each signer goes pending → sent → viewed → signed, or declined. After the last signature, completed arrives within seconds, once the PDFs are signed and timestamped.

Errors

Errors return an HTTP status and an error object with a stable code and a readable message. Validation errors include details with the affected field.

HTTP/1.1 402 Payment Required
{
  "error": {
    "code": "insufficient_credits",
    "message": "Not enough signatures to send this envelope.",
    "details": { "needed": 3, "available": 1 }
  }
}
400
Malformed JSON.
401
Missing, invalid or revoked key.
402
Not enough signatures or SMS (insufficient_credits, sms_no_credits).
403
No active Pro plan (subscription_required) or unconfirmed email.
404
The resource does not exist or is not yours.
409
The current status does not allow the operation (envelope_not_draft, not_cancelable).
413
Document too large for an inline upload.
422
Invalid data or unsupported document.
429
Rate limit exceeded.

Limits and pagination

Each key allows 120 requests per minute; the X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers show your usage and, when exceeded, Retry-After says when to retry. Per envelope: up to 10 documents (25 MB each) and 10 signers. Lists return has_more; request the next page with starting_after set to the last item's id.

Webhooks

Set an HTTPS URL in Settings → API and webhooks to receive a POST on every status change. Reply with any 2xx; on failure we retry twice. Every request carries the DocuFirma-Signature header so you can check it comes from us.

envelope.sent
The envelope was sent to the signers.
envelope.signed
A signer signed (data.signer_id).
envelope.completed
Everyone signed and the PDFs are timestamped and ready.
envelope.declined
A signer declined to sign.
envelope.expired
The envelope expired before completion.
envelope.canceled
You canceled the envelope.
POST /webhooks/docufirma HTTP/1.1
Content-Type: application/json
DocuFirma-Signature: t=1793790902,v1=5f0c4e…

{
  "id": "evt_9b1d…",
  "object": "event",
  "type": "envelope.completed",
  "created_at": "2026-11-03T10:42:11Z",
  "data": { "envelope": { "id": "6c36f47e-…", "status": "completed", … } }
}

Verify the signature: compute the HMAC-SHA256 of “t.body” with your secret and compare it with v1. Reject messages whose t is older than 5 minutes.

Node.js
import crypto from "node:crypto";

export function verifyDocuFirma(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}