IDCanopy Developers
QES identify and sign

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

FieldTypeRequiredDescription
person.emailstringyesThe person's email address.
person.phonestringyesE.164, for example +436601234567.
signature_fieldsstring arrayyes1 to 20 ids of the signature fields in the PDF you will upload, signed by the person.
redirect_urlstringnoHTTPS URL the person returns to when done.
referencestringnoYour 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.

FieldDescription
first_name, last_nameAs identified. Use them to personalise the document.
date_of_birthDate.
nationalityISO 3166-1 alpha-2.
document.typeFor example ID_CARD or PASSPORT.
document.issuing_country, document.expiry_date
completed_atWhen identification finished.

signature, from completed: evidence of the qualified signature.

FieldDescription
signed_atWhen the person signed.
levelqualified.
certificateThe 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.pdf

A 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.pdf

Cancel 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.

On this page