Add traceable electronic-signature flows to your apps. REST + JSON.
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) →
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();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"Send an HTML contract: SignCloud renders it to PDF and sends it for signing. Ideal when you don't have a PDF.
| Field | Type | Description |
|---|---|---|
name | string | Document name (required). |
html | string | HTML body of the contract (required). |
recipients | array | Signers: {name, email, phone}. Mobile required. |
expires_at | string | YYYY-MM-DD (optional, 30 days default). |
return_url | string | https URL offered as a button after signing (optional, no automatic redirect). |
retention_years | integer | Evidence package retention: 10, 20, or 50 years. |
verification | string | siret, identity (ID + selfie), or both. SMS remains mandatory. |
identity_provider | string | choice, signcloud_nfc, franceconnect or stripe. The selected method is enforced server-side. |
require_personal_certificate | boolean | Requires 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);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/…" }
}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}'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' }],
});Filters: status (DRAFT, SENT, COMPLETED…), limit (1–100).
Returns the detailed status and signers (PENDING / WAITING / SIGNED).
Returns the sealed PDF (once the document is COMPLETED). Binary application/pdf response.
Reminds the pending signer (new link) or cancels a document in progress.
SignCloud notifies your URL at each step. Events: recipient.signed, document.completed.
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": "…" }]
}
}For multiple subscriptions (Zapier, Make…) that coexist with the main webhook.
| HTTP | error | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key. |
| 422 | invalid | Missing/invalid field (see message). |
| 422 | idempotency_key_invalid / idempotency_key_reused | Invalid idempotency key or key reused with a different body. |
| 429 | quota_exceeded | Monthly document quota reached. |
| 409 | invalid_state / not_ready | Action not possible in the current state. |
| 404 | not_found | Document not found. |
Errors return { "error": "...", "message": "..." }.
Single-file, dependency-free clients for PHP and JavaScript/Node. They cover every endpoint and webhook verification.