Sessions
Create a session, read it, upload the document, download the signed PDF and cancel
Available on request. Contact IDCanopy for access; details may change. Test environment only.
The examples use $QES_BASE_URL for the test base URL, which is shared on request.
Create a session
POST /qes-onboarding/sessions
| Field | Type | Required | Description |
|---|---|---|---|
person.email | string | yes | The person's email address. |
person.phone | string | yes | E.164, for example +436601234567. |
signature_fields | string array | yes | 1 to 20 ids of the signature fields in the PDF you will upload, signed by the person. |
redirect_url | string | no | HTTPS URL the person returns to when done. |
reference | string | no | Your own reference, up to 200 characters, echoed in the session and in webhooks. |
Unknown fields are rejected.
curl -s -X POST "$QES_BASE_URL/qes-onboarding/sessions" \
-H "Authorization: Bearer $QES_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"person": { "email": "erika.mustermann@example.com", "phone": "+436601234567" },
"signature_fields": ["Signature_1"],
"redirect_url": "https://app.example.com/onboarding/done",
"reference": "contract-42"
}'A 201 returns the session. Send the person to url; it works until expires_at.
{
"session_id": "qes_5f1c2a9e0b7d4c3a8e6f1b2c",
"status": "identifying",
"url": "https://sign.example.com/s/abc123",
"expires_at": "2026-10-22T10:00:00Z",
"reference": "contract-42",
"failure_reason": null,
"identification": null,
"signature": null,
"history": [
{ "status": "created", "at": "2026-10-15T10:00:00Z" },
{ "status": "identifying", "at": "2026-10-15T10:00:01Z" }
],
"created_at": "2026-10-15T10:00:00Z",
"updated_at": "2026-10-15T10:00:01Z"
}Read a session
GET /qes-onboarding/sessions/{session_id} returns the session with its status and history. Two
blocks fill in as the session moves on:
identification, from awaiting_document: the verified identity. Images of the identity
document and its number are not returned.
| Field | Description |
|---|---|
first_name, last_name | As identified. Use them to personalise the document. |
date_of_birth | Date. |
nationality | ISO 3166-1 alpha-2. |
document.type | For example ID_CARD or PASSPORT. |
document.issuing_country, document.expiry_date | |
completed_at | When identification finished. |
signature, from completed: evidence of the qualified signature.
| Field | Description |
|---|---|
signed_at | When the person signed. |
level | qualified. |
certificate | The signer's qualified certificate: subject, issuer, serial_number, valid_from, valid_to. |
url is null once the session is final.
Upload the document
PUT /qes-onboarding/sessions/{session_id}/document, body the raw PDF (application/pdf, up to
10 MiB). Allowed only while the session is awaiting_document; any other state is a 409
wrong_state. The signature fields named at creation must exist in the PDF.
curl -s -X PUT "$QES_BASE_URL/qes-onboarding/sessions/$SESSION_ID/document" \
-H "Authorization: Bearer $QES_TOKEN" \
-H "Content-Type: application/pdf" \
--data-binary @contract-42.pdfA 200 returns the session in signing; the person can now sign. If the upload fails with a 502,
the session stays in awaiting_document and you can upload again.
If no document is uploaded, the session ends with failure_reason: document_not_uploaded.
Download the signed PDF
GET /qes-onboarding/sessions/{session_id}/signed-document returns the signed PDF (PAdES) once the
session is completed; a 409 before that.
curl -s "$QES_BASE_URL/qes-onboarding/sessions/$SESSION_ID/signed-document" \
-H "Authorization: Bearer $QES_TOKEN" -o contract-42-signed.pdfCancel a session
POST /qes-onboarding/sessions/{session_id}/cancel ends a session that is not finished. The link
stops working, and the session is cancelled with failure_reason: cancelled_by_client. A session
that is already final is a 409.
Errors
See Errors.