Quickstart: first envelope with two signers
In five steps you send a PDF to two people for signing, learn by webhook when both have finished, and download the signed document. All examples use a test key: nothing is charged in test mode, and with the addresses from the guide "Sandbox scenarios" the recipients even sign on their own.
This guide is the English version of the German guide quickstart and covers the same steps.
Basics that apply to every route:
- Base URL: your API base URL (
$BASE_URLin the examples), key asAuthorization: Bearer $KEY. - Responses are the object itself (with
object, for exampleenvelope), lists are{ data, hasMore, nextCursor }, errors are{ error: { code, type, message, details, requestId } }. - Writing calls accept an
Idempotency-Key: if you repeat a call with the same key and the same body, you get the stored response instead of a second envelope. - Client timeout: at least 30 seconds.
POST /v1/signaturesusually answers within 25 seconds (counted from receipt; preparing a large document counts towards them and is never interrupted), finished (200) or with 202status: WAIT_SIGNandRetry-After; the result then arrives by webhook orGET /v1/signatures/{id}(German guideqes-members, section on response time).
1. Check the key
In the dashboard, under Developers → API keys, create a test key (qgw_test_…). For this guide it needs the scopes envelopes:read, envelopes:write and webhooks:manage.
curl "$BASE_URL/v1/me" -H "Authorization: Bearer $KEY"
GET /v1/me shows the organization, the mode (TEST), the scopes and the rate limits of the key.
2. Create a webhook subscription
So that you do not have to poll, subscribe to the events of envelopes:
curl -X POST "$BASE_URL/v1/webhook-subscriptions" \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-H 'Idempotency-Key: quickstart-subscription-1' \
-d '{ "url": "https://example.com/hooks/signatures", "events": ["envelope.*", "recipient.*"] }'
The response contains secret (whsec_…) this one time only. Store it: it verifies the signature of every delivery (see the guide "Receiving and verifying webhooks"). A test key creates a subscription in test mode, which only receives test events.
3. Create and send an envelope
An envelope bundles documents, recipients and fields. With send: true it is created and sent in one call:
curl -X POST "$BASE_URL/v1/envelopes" \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-H 'Idempotency-Key: quickstart-envelope-1' \
-d '{
"title": "Rental agreement, 1 Sample Street",
"externalId": "crm-4711",
"expiresInDays": 14,
"signingOrder": "SEQUENTIAL",
"documents": [{ "name": "Rental-agreement.pdf", "base64": "JVBERi0xLjcK…" }],
"recipients": [
{ "recipientKey": "tenant", "role": "SIGNER", "firstName": "Anna", "lastName": "Weber",
"email": "anna.weber@example.com", "signatureLevel": "SES" },
{ "recipientKey": "landlord", "role": "SIGNER", "firstName": "Jonas", "lastName": "Keller",
"email": "jonas.keller@example.com", "signatureLevel": "SES" }
],
"send": true
}'
base64takes PDFs up to 11 MB (the length of the base64 text). Upload larger files beforehand withPOST /v1/documentsor pass afileUrl; the document then carriesdocumentIdorfileUrlinstead ofbase64.- Without fields, every signer gets a signature field on the last page. Set your own fields with
fields(page and rectangle in PDF points). signingOrder: SEQUENTIALinvites the second person only when the first has finished;PARALLELinvites both at once.signatureLevelis the simple electronic signature (SES) here. You chooseAES(advanced) andQES(qualified) per recipient; a QES is only possible for members of your organization who hold a certificate (German guideqes-members). The own simple signature (signing with a one-time code directly on our signing page) is currently available in test mode only.
To see before sending whether everything is in order and what it costs, send the same body to POST /v1/envelopes?dryRun=true: the response is a preview (envelope_send_preview with valid, errors, warnings and costPreview), and nothing is created.
Alternatively, create a draft first (without send), complete it with POST /v1/envelopes/{id}/recipients, POST /v1/envelopes/{id}/documents and POST /v1/envelopes/{id}/fields, and then send it with POST /v1/envelopes/{id}/send.
4. React to events
Your endpoint receives, among others and in this order:
| Event | Meaning |
|---|---|
envelope.sent | The envelope was sent. |
recipient.notified | A person is next, the invitation is on its way. |
recipient.signed | A person has signed. |
envelope.completed | Everyone has finished; the final PDF and the audit trail are ready. |
Every event carries the envelopeId and your externalId in context, and in data the object as returned by GET /v1/envelopes/{id}. Answer quickly with 2xx and process in the background. You can read the current state at any time with GET /v1/envelopes/{id} and the timeline with GET /v1/envelopes/{id}/events.
Without a webhook endpoint (for example while trying things out), poll GET /v1/events: it lists the events of the last 30 days, newest first.
5. Download the result
After envelope.completed:
curl -o Rental-agreement-signed.pdf "$BASE_URL/v1/envelopes/$ENVELOPE_ID/documents/final" \
-H "Authorization: Bearer $KEY"
curl -o Audit-trail.pdf "$BASE_URL/v1/envelopes/$ENVELOPE_ID/audit-trail" \
-H "Authorization: Bearer $KEY" -H 'Accept: application/pdf'
GET /v1/envelopes/{id}/documents/final returns the final PDF (with ?format=base64 as the JSON object file), GET /v1/envelopes/{id}/audit-trail the audit trail as JSON or, with Accept: application/pdf, as a PDF. For systems without an API key, POST /v1/envelopes/{id}/download-links creates links that are valid for 15 minutes.
What next?
- Recurring documents: the German guide
templates(/docs/guides/templates.md). - Test runs without real people: the guide "Sandbox scenarios" (
/docs/guides/sandbox-en.md). - Costs in advance: the German guide
costs(/docs/guides/costs.md). - All routes, fields and error codes: the API reference at
/docs.