Inkr API

Templates

Créer un template figé pour réutiliser le même PDF et les mêmes positions de champs sur N submissions.

Un template est un PDF + une liste de champs (signature, date, texte, etc.) à des positions définies. Vous créez un template une seule fois et vous envoyez N submissions à partir de lui.

Si vous générez un PDF différent à chaque appel (par exemple un contrat avec un tableau variable par signataire), utilisez plutôt POST /v1/submissions/from_pdf qui crée le template en interne pour vous.

Types de champs

8 types sémantiques couvrant l'essentiel des cas d'usage signature :

TypeDescriptionAttributs spécifiques
signatureZone de signatureaucun
initialsParaphesaucun
dateDateformat (chaîne libre, 80 caractères max)
textTexte librevalidation_pattern (regex ECMAScript, 500 caractères max)
checkboxCase à cocheraucun
numberNombreaucun
radioChoix uniqueoptions obligatoire, 2 à 50 entrées
selectListe déroulanteoptions obligatoire, 2 à 50 entrées

Attributs communs : name, signer_role, required (défaut false), readonly (défaut false), default_value, order_index.

format n'est accepté que sur un champ date et options que sur radio / select. Les fournir ailleurs renvoie 422. Les regex à quantificateurs imbriqués ((a+)+, (.*)*) sont rejetées pour éviter un déni de service par backtracking.

Créer un template

POST /v1/templates accepte le PDF en base64 ou via URL, avec une liste de champs et leurs positions.

Format des coordonnées sur cet endpoint. Les coordonnées sont plates sur l'objet champ (page, x, y, width, height), pas dans un tableau areas, exprimées uniquement en fractions de 0 à 1. page est 1-indexé. C'est la différence principale avec /from_pdf, qui utilise areas[] avec w / h et accepte aussi les points PDF.

curl -X POST https://api.getinkr.eu/v1/templates \
  -H "Authorization: Bearer $INKR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Contrat partenariat v3",
    "pdf_base64": "JVBERi0xLjQK...",
    "fields": [
      {
        "name": "signature_partenaire",
        "type": "signature",
        "signer_role": "Partenaire",
        "required": true,
        "page": 1,
        "x": 0.6,
        "y": 0.85,
        "width": 0.3,
        "height": 0.05
      },
      {
        "name": "date_signature",
        "type": "date",
        "signer_role": "Partenaire",
        "format": "DD/MM/YYYY",
        "page": 1,
        "x": 0.1,
        "y": 0.85,
        "width": 0.15,
        "height": 0.03
      }
    ]
  }'
Champ du bodyTypeDétail
namestring1 à 200 caractères. Requis.
slugstringKebab-case, 120 caractères max. Généré depuis name si absent. Unique par compte, sinon 409.
pdf_base64stringPDF en base64. Les data URLs data:application/pdf;base64,… sont acceptées.
pdf_urlstringURL HTTPS publique, 2048 caractères max.
fieldsarray1 à 500 champs. Requis.

Fournissez pdf_base64 ou pdf_url, jamais les deux ni aucun des deux. Limite de taille du PDF décodé : 50 Mo. En envoi inline, la contrainte réellement bloquante reste la limite de corps de requête de la plateforme (4,5 Mo) : au-delà, passez par pdf_url.

Contraintes sur une zone : page entre 1 et 500, width et height strictement positifs. x + width comme y + height doivent rester ≤ 1.

Réponse 201 (extrait) :

{
  "id": "tpl_01J5HZ...",
  "name": "Contrat partenariat v3",
  "slug": "contrat-partenariat-v3",
  "status": "draft",
  "created_via": "api",
  "created_at": "2026-05-15T14:32:08.421Z",
  "updated_at": "2026-05-15T14:32:08.421Z",
  "fields_count": 2,
  "pdf_url": null,
  "fields": [{ "id": "...", "type": "signature", "page": 1, "...": "..." }]
}

pdf_url vaut toujours null sur l'API publique : le PDF n'est pas re-signé à chaque lecture. Pour récupérer un document, passez par GET /v1/submissions/{id}/documents.

Lister les templates

curl "https://api.getinkr.eu/v1/templates?limit=20&status=active" \
  -H "Authorization: Bearer $INKR_API_KEY"

Cursor pagination. Filtres : status (draft, active, archived) et created_via (ui, api).

{
  "data": [{ "id": "tpl_01J5HZ...", "...": "..." }],
  "has_more": true,
  "next_cursor": "MjAyNi0wNS0xNVQxNDozMjowOFp8OTBjZGE..."
}

has_more et next_cursor sont à la racine de la réponse, pas dans un objet meta. next_cursor vaut null en fin de liste. Le curseur est opaque : ne le décodez pas.

Détail et suppression

curl https://api.getinkr.eu/v1/templates/tpl_01J5HZ... \
  -H "Authorization: Bearer $INKR_API_KEY"

curl -X DELETE https://api.getinkr.eu/v1/templates/tpl_01J5HZ... \
  -H "Authorization: Bearer $INKR_API_KEY"

DELETE archive le template (status archived) et renvoie 200 :

{ "deleted": true, "id": "tpl_01J5HZ...", "status": "archived" }

Les submissions déjà créées avec ce template restent intactes (préservation eIDAS). Un template archivé ne peut plus servir de source à une nouvelle submission (422 template_archived). Aucune Idempotency-Key n'est requise sur DELETE.