API & developers

Add traceable electronic-signature flows to your apps. REST + JSON.

⬇ Download the SDK (PHP + JS)

Introduction

The SignCloud API is a REST API: HTTPS requests, JSON bodies and responses. All URLs are prefixed with https://signcloud.fr/api/v1.

Key rule: each signer must have a mobile number — signatures are verified by SMS code.

Using invoicing software? Sellsy, Axonaut, Pennylane recipes (Make / n8n) →

Authentication

Pass your API key in the Authorization: Bearer <clé> (or X-Api-Key). Generate it from Account → API & Webhooks.

curl https://signcloud.fr/api/v1/ping \
  -H "Authorization: Bearer VOTRE_CLE_API"
$sc = new SignCloud\Client('VOTRE_CLE_API');
$sc->ping();
const sc = new SignCloud('VOTRE_CLE_API');
await sc.ping();

Creation idempotency

For every document creation, send a stable business key in Idempotency-Key (8–200 characters). An identical retry returns the initial response with Idempotency-Replayed: true without creating or sending a second document. Reusing the key with a different body is rejected with 422.

-H "Idempotency-Key: commande-1024-contrat-v1"

Create a document (HTML)

POST /api/v1/documents/html

Send an HTML contract: SignCloud renders it to PDF and sends it for signing. Ideal when you don't have a PDF.

FieldTypeDescription
namestringDocument name (required).
htmlstringHTML body of the contract (required).
recipientsarraySigners: {name, email, phone}. Mobile required.
expires_atstringYYYY-MM-DD (optional, 30 days default).
return_urlstringhttps URL offered as a button after signing (optional, no automatic redirect).
retention_yearsintegerEvidence package retention: 10, 20, or 50 years.
verificationstringsiret, identity (ID + selfie), or both. SMS remains mandatory.
identity_providerstringchoice, signcloud_nfc, franceconnect or stripe. The selected method is enforced server-side.
require_personal_certificatebooleanRequires a PAdES signature using the signer’s personal certificate in a compatible native app. The private key never leaves its device.
curl -X POST https://signcloud.fr/api/v1/documents/html \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Contrat",
    "html": "<h1>Contrat</h1><p>…</p>",
    "recipients": [{"name":"Jean Dupont","email":"jean@ex.com","phone":"+33612345678"}]
  }'
$doc = $sc->createFromHtml([
  'name' => 'Contrat',
  'html' => '<h1>Contrat</h1><p>…</p>',
  'recipients' => [[
    'name' => 'Jean Dupont', 'email' => 'jean@ex.com', 'phone' => '+33612345678',
  ]],
]);
echo $doc['id'];
const doc = await sc.createFromHtml({
  name: 'Contrat',
  html: '<h1>Contrat</h1><p>…</p>',
  recipients: [{ name: 'Jean Dupont', email: 'jean@ex.com', phone: '+33612345678' }],
});
console.log(doc.id);

FranceConnect & public services

POST /api/v1/partner/signature-requests

This endpoint lets an authorised public service create a document and redirect the user to the returned sign_url. FranceConnect authenticates identity; SignCloud handles PDF review, consent, SMS, signature and evidence.

The body matches /api/v1/documents. Use identity_provider="franceconnect", an HTTPS return_url, a webhook, and a stable Idempotency-Key. Production activation requires DINUM approval and FranceConnect/FranceConnect+ credentials.

curl -X POST https://signcloud.fr/api/v1/partner/signature-requests \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Idempotency-Key: inpi-formalite-2026-00042" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Formalité INPI",
    "pdf_base64": "JVBERi0xLjc…",
    "identity_provider": "franceconnect",
    "return_url": "https://demarches.exemple.fr/dossiers/42",
    "recipients": [{"name":"Jean Dupont","email":"jean@exemple.fr","phone":"+33612345678"}]
  }'

Response (201):

{
  "id": "11111111-1111-4111-8111-111111111111",
  "name": "Contrat",
  "status": "SENT",
  "signers": [{ "email": "jean@ex.com", "status": "PENDING", "sign_url": "https://signcloud.fr/doc/…" }],
  "recipient": { "sign_url": "https://signcloud.fr/doc/…" }
}

Standalone SignCloud Identity API

POST /api/identity/v1/verifications

For clients who only need identity verification, with no document to sign. The API returns a dedicated white-label page, an NFC app deep link, and a pollable status. VERIFIED is returned only after NFC checks, live selfie, presentation-attack detection, and external evidence deposit.

The same service is available without code in the Identity dashboard. An Identity-only plan hides documents and only exposes this journey, branding, and settings.

Once verified, the client retrieves the JSON assertion and PDF certificate through the API. The verified person can also download a minimized certificate from their secure link; no selfie, DG2 portrait, full document number, or raw certificate is included.

Download the Identity OpenAPI contract →

curl -X POST https://signcloud.fr/api/identity/v1/verifications \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Idempotency-Key: controle-client-0042" \
  -H "Content-Type: application/json" \
  -d '{"reference":"client-0042","return_url":"https://votre-site.fr/controle/termine","retention_years":10}'

Create a document (PDF)

POST /api/v1/documents

Send an existing PDF for signing. The PDF is base64-encoded in pdf_base64.

Options retention_years, verification, return_url and the Idempotency-Key header work exactly as for HTML creation.

curl -X POST https://signcloud.fr/api/v1/documents \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mandat",
    "pdf_base64": "JVBERi0xLjc…",
    "recipients": [{"name":"Jean","email":"jean@ex.com","phone":"+33612345678"}]
  }'
$doc = $sc->createDocument(
  ['name' => 'Mandat', 'recipients' => [[
    'name' => 'Jean', 'email' => 'jean@ex.com', 'phone' => '+33612345678',
  ]]],
  file_get_contents('mandat.pdf') // encodé en base64 par le SDK
);
import { readFileSync } from 'fs';
const doc = await sc.createDocument({
  name: 'Mandat',
  pdf_base64: readFileSync('mandat.pdf').toString('base64'),
  recipients: [{ name: 'Jean', email: 'jean@ex.com', phone: '+33612345678' }],
});

List documents

GET /api/v1/documents?status=SENT&limit=50

Filters: status (DRAFT, SENT, COMPLETED…), limit (1–100).

Get a document

GET /api/v1/documents/{id}

Returns the detailed status and signers (PENDING / WAITING / SIGNED).

Download signed PDF

GET /api/v1/documents/{id}/signed

Returns the sealed PDF (once the document is COMPLETED). Binary application/pdf response.

Remind / Cancel

POST /api/v1/documents/{id}/remind
POST /api/v1/documents/{id}/cancel

Reminds the pending signer (new link) or cancels a document in progress.

Webhooks

SignCloud notifies your URL at each step. Events: recipient.signed, document.completed.

GET /api/v1/webhook  — list your webhooks
POST /api/v1/webhook  { webhook_url, label? }

Idempotent per URL: call it from each site (PrestaShop, WordPress…) to register several webhooks — each receives all events and gets ITS own secret (returned in webhook_secret). Each delivery is signed X-SignCloud-Signature: sha256=<hmac>. Verify it:

// $secret : renvoyé à la création du webhook
if (!SignCloud\Client::verifyWebhook(
  file_get_contents('php://input'),
  $_SERVER['HTTP_X_SIGNCLOUD_SIGNATURE'] ?? '',
  $secret
)) { http_response_code(401); exit; }
const ok = SignCloud.verifyWebhook(
  rawBody,
  req.headers['x-signcloud-signature'],
  secret
);
if (!ok) return res.status(401).end();

Received body:

{
  "event": "document.completed",
  "sent_at": "2026-08-09T10:12:00Z",
  "tenant": "…",
  "data": {
    "document": { "id": "…", "name": "Contrat", "sha256": "…", "signed_pdf_url": "…" },
    "signers": [{ "name": "Jean Dupont", "email": "jean@ex.com", "signed_at": "…" }]
  }
}

REST Hooks

For multiple subscriptions (Zapier, Make…) that coexist with the main webhook.

POST /api/v1/hooks  { target_url, event }
DELETE /api/v1/hooks/{id}

Error codes

HTTPerrorMeaning
401unauthorizedMissing or invalid API key.
422invalidMissing/invalid field (see message).
422idempotency_key_invalid / idempotency_key_reusedInvalid idempotency key or key reused with a different body.
429quota_exceededMonthly document quota reached.
409invalid_state / not_readyAction not possible in the current state.
404not_foundDocument not found.

Errors return { "error": "...", "message": "..." }.

Official SDKs

Single-file, dependency-free clients for PHP and JavaScript/Node. They cover every endpoint and webhook verification.

⬇ Download the SDK