Inkr API

Submissions

Envoyer un document à signer, suivre son statut, récupérer le PDF final et l'audit eIDAS.

Une submission est une instance concrète de signature : un PDF + une liste de signataires + un statut.

Depuis un template

curl -X POST https://api.getinkr.eu/v1/submissions \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "template_id": "tpl_01J5HZ...",
    "signing_order": "preserved",
    "expires_at": "2026-06-15T23:59:59Z",
    "redirect_url": "https://app.example.com/contracts/42/signed",
    "metadata": { "internal_contract_id": "k_42" },
    "submitters": [
      {
        "role": "Partenaire",
        "email": "alice@example.com",
        "name": "Alice Dupont",
        "external_id": "partner_42",
        "metadata": { "department": "sales" },
        "fields": { "raison_sociale": "ACME SARL" }
      }
    ],
    "send_email": true
  }'

signing_order : preserved (les submitters signent dans l'ordre de l'array, le 2e ne reçoit son mail qu'après signature du 1er) ou random (tous reçoivent leur mail en même temps).

Depuis un PDF inline

Utilisez cette variante si votre PDF est généré dynamiquement à chaque appel (contrats, factures, émargements avec lignes variables). Inkr crée un template interne archivé immédiatement et fait pointer la submission dessus.

curl -X POST https://api.getinkr.eu/v1/submissions/from_pdf \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "documents": [
      { "name": "Émargement S20", "pdf_base64": "JVBERi0xLjQK..." }
    ],
    "submitters": [
      {
        "role": "Employé",
        "email": "bob@example.com",
        "fields": [
          {
            "name": "signature_employe",
            "type": "signature",
            "required": true,
            "areas": [{ "page": 0, "x": 0.5, "y": 0.9, "w": 0.3, "h": 0.05 }]
          }
        ]
      }
    ],
    "send_email": true
  }'

Où vivent les champs. Les champs porteurs de zones appartiennent au document (documents[0].fields[]), avec name, type, role et areas. La forme ci-dessus, qui les déclare sur submitters[].fields[], reste acceptée : Inkr les remonte automatiquement sur le document en injectant le role du submitter parent. Les deux écritures fonctionnent, la forme document est la forme canonique.

Le PDF décodé peut faire jusqu'à 50 Mo. En envoi inline, la contrainte réellement bloquante est la limite de corps de requête de la plateforme (4,5 Mo) : au-delà, passez documents[].file (ou son alias pdf_url) à une URL HTTPS publique.

Depuis un HTML inline

Utilisez cette variante si vous générez des documents HTML dynamiquement (feuilles d'émargement, contrats, factures avec données inline). Inkr rend le HTML en PDF via Puppeteer + Chromium, extrait les zones signature depuis les variables tag embarquées.

curl -X POST https://api.getinkr.eu/v1/submissions/from_html \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Feuille d émargement S21",
    "html": "<html><body><h1>Feuille d émargement</h1><p>Manager : {{manager_sig;role=Manager;type=signature;readonly=true}}</p><p>Employé : {{employee_sig;role=Employee;type=signature}}</p></body></html>",
    "size": "A4",
    "send_email": true,
    "reply_to": "support@example.com",
    "submitters": [
      {
        "email": "manager@example.com",
        "role": "Manager",
        "completed": true,
        "send_email": false,
        "fields": [
          { "name": "manager_sig", "readonly": true, "default_value": "data:image/png;base64,iVBORw0K..." }
        ]
      },
      {
        "email": "alice@example.com",
        "role": "Employee",
        "name": "Alice Dupont"
      }
    ]
  }'

Syntax des variables tag : {{Field;role=X;type=Y;required=true;readonly=false}}

AttributValeurUsage
rolestringrôle signataire. Doit matcher un role dans submitters[].
typesignature / initials / date / text / checkbox / number / radio / selecttype du champ. Default signature.
requiredtrue / falseobligatoire ? Default true.
readonlytrue / falseverrouillé ? Default false.

Pattern submitter pré-signé : si un submitter a completed: true + fields: [{ name, readonly, default_value }], sa signature est apposée immédiatement à la création. Il ne reçoit pas d'email signing. Cas d'usage : un manager qui pré-signe un document généré côté backend. Conforme audit eIDAS (event submitter.pre_signed enregistré avec metadata source + timestamp).

Limites :

  • Body 4 MB max.
  • HTML self-contained obligatoire (images base64 inline). Toutes les ressources externes sont bloquées (zéro fuite possible via <img src=externe>).
  • JavaScript désactivé côté rendu (<script> ignorés).
  • Pages A4 (595×842 pt) ou Letter. Multi-pages auto-paginated.

Depuis un DOCX inline

Mêmes principes que /from_html mais avec un DOCX OOXML en base64. Pipeline 2-pass : mammoth.js convertit DOCX → HTML en préservant les {{Field;...}}, puis le pipeline /from_html prend le relais.

DOCX_BASE64=$(base64 -i contrat-employee.docx)
curl -X POST https://api.getinkr.eu/v1/submissions/from_docx \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Contrat employé - Alice Dupont",
    "file": "'"$DOCX_BASE64"'",
    "size": "A4",
    "send_email": true,
    "reply_to": "support@example.com",
    "submitters": [
      {
        "email": "manager@example.com",
        "role": "Manager",
        "completed": true,
        "fields": [
          { "name": "Manager", "readonly": true, "default_value": "data:image/png;base64,iVBORw0K..." }
        ]
      },
      {
        "email": "alice@example.com",
        "role": "Employee",
        "name": "Alice Dupont"
      }
    ]
  }'

Le DOCX doit contenir les variables {{Manager;role=Manager;type=signature;readonly=true}} + {{Signature;role=Employee;type=signature}} (ou équivalents) dans le texte plain. Mammoth.js les préserve à la conversion. 4 MB max sur le base64.

Statuts

Une submission passe par 8 statuts possibles :

StatusSens
createdCréée mais pas encore envoyée (rare si send_email: true).
sentEmail envoyé au premier submitter, en attente de signature.
viewedAu moins un submitter a ouvert le signing URL.
partially_signedAu moins un mais pas tous les submitters ont signé.
completedTous les submitters ont signé. PDF final disponible.
declinedUn submitter a refusé de signer.
expiredexpires_at dépassé.
cancelledAnnulée via DELETE.

Côté signataire, les statuts possibles sont pending, opened, signed, declined et pre_signed (signature apposée en amont via completed: true).

Options communes aux 4 endpoints de création

ChampTypeDétail
submittersarray1 à 50 signataires. Requis.
send_emailbooleanDéfaut true.
signing_orderenumpreserved (défaut) ou random.
expires_atstringISO 8601, doit être dans le futur sinon 422.
redirect_urlstring2048 caractères max.
bcc_email, reply_tostringEmails, 320 caractères max.
metadataobjectClés 100 caractères max, valeurs string (2000 max), number, boolean ou null.
message.subject / message.bodystring200 et 5000 caractères max.

Sur un submitter : role (requis), email (requis), name, phone, external_id, metadata, fields, send_email, completed, require_email_2fa.

Double authentification email. Passez require_email_2fa: true sur un submitter pour lui envoyer un code à usage unique (valable 10 minutes) qu'il devra saisir avant d'accéder au document. Défaut false. require_phone_2fa est accepté par le schéma pour compatibilité mais toute valeur true renvoie 422 phone_2fa_not_supported : Inkr n'opère pas d'infrastructure SMS.

Récupérer un PDF signé

curl https://api.getinkr.eu/v1/submissions/sub_01J5HZ.../documents \
  -H "Authorization: Bearer $INKR_API_KEY"
{
  "submission_id": "sub_01J5HZ...",
  "status": "completed",
  "original_pdf_url": "https://...?token=...",
  "signed_pdf_url": "https://...?token=...",
  "url_expires_at": "2026-05-15T15:32:08.421Z"
}

Les deux URLs sont signées et valables 1h. signed_pdf_url vaut null tant que la submission n'est pas complétée. Le PDF signé porte les signatures incrustées et le footer eIDAS SES.

Audit log eIDAS

Disponible uniquement quand status: "completed" :

curl https://api.getinkr.eu/v1/submissions/sub_01J5HZ.../audit_log \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -o audit.pdf

Le PDF contient le détail de tous les événements horodatés : envoi, ouverture, IP, user-agent, signature, hash SHA-256 final.

Lister les submissions

curl "https://api.getinkr.eu/v1/submissions?status=completed&limit=50&cursor=..." \
  -H "Authorization: Bearer $INKR_API_KEY"

Filtres supportés : status et template_id. Cursor pagination, réponse au format { data, has_more, next_cursor } à la racine.

Submitters (endpoints dédiés)

Pour interroger les submitters individuellement (utile pour matcher avec votre DB via external_id) :

# Lister tous les submitters d'un user
curl "https://api.getinkr.eu/v1/submitters?status=signed&limit=50" \
  -H "Authorization: Bearer $INKR_API_KEY"

# Détail d'un submitter (avec values signées)
curl https://api.getinkr.eu/v1/submitters/sbm_01J5HZ... \
  -H "Authorization: Bearer $INKR_API_KEY"

# Mettre à jour email/phone/name d'un submitter en pending
curl -X PATCH https://api.getinkr.eu/v1/submitters/sbm_01J5HZ... \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "email": "alice.new@example.com" }'

PATCH submitter n'est autorisé que si status est pending ou opened, sinon 409 submitter_already_finalized. Au moins un des trois champs email, phone ou name doit être fourni. Si l'email change, un nouveau mail de demande de signature part automatiquement vers la nouvelle adresse. Aucune Idempotency-Key n'est requise.

Filtres de GET /v1/submitters : status (pending, opened, signed, declined, pre_signed), submission_id et email.

Journal des events

GET /v1/events expose le journal complet des transitions, y compris les events de granularité signataire (submitter.opened, submitter.signed, submitter.pre_signed) qui ne sont pas livrables par webhook.

curl "https://api.getinkr.eu/v1/events?type=submitter.signed&limit=100" \
  -H "Authorization: Bearer $INKR_API_KEY"

Filtres : type et submission_id.