Overview
The Invitation Model is Sadq's document-centric signing approach. Your system uploads a PDF, defines the signers and their authentication method, and Sadq handles delivery (email/SMS), identity verification, and returns the signed document — either via webhook or on-demand download.
Key characteristics:
- Document is uploaded to Sadq servers.
- Signer identity is verified by Sadq using Nafath, Absher, SMS OTP, Email OTP, or WhatsApp.
- Signer is redirected to Sadq's secure signing interface (or you can embed the link).
- Signed PDF is returned to your system — in the webhook payload or via download API.
Workflow Definitions
This section defines the exact sequence of API calls required for each common task.
Workflow 1: Send a document to a signer for signing
Use this workflow when you want to upload a PDF and have one or more people sign it electronically.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Authenticate | POST /Authentication/Authority/Token | Get a Bearer token to authorize all other calls |
| 2 | Upload document | POST /api/v1/envelopes/initiate-base64 | Upload the PDF — receive documentId and envelopeId |
| 3 | Invite signer(s) | POST /api/v3/invitations | Define who signs, how they authenticate, where to sign |
| 4 | Receive result | Webhook callback (or GET /api/v1/envelopes/{id}/status) | Get notified when signing is done |
| 5 | Download signed PDF | GET /api/v1/documents/{id}/signed | Download the signed document |
Note: Steps 4 and 5 are alternatives. If you registered a webhook, the signed file arrives automatically in the webhook payload — no need to call the download endpoint.
Workflow 2: Send multiple documents in one envelope
Use this workflow when multiple PDFs need to be signed together by the same set of signers.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Authenticate | POST /Authentication/Authority/Token | Get a Bearer token |
| 2 | Upload documents | POST /api/v1/envelopes/bulk/initiate-base64 | Upload multiple PDFs in one envelope |
| 3 | Invite signer(s) | POST /api/v1/invitations/envelope | Send invitations using envelopeId |
| 4 | Receive result | Webhook or GET /api/v1/envelopes/{id}/status | Track completion status |
| 5 | Download all files | GET /api/v1/envelopes/{id}/files/completed | Download all signed documents |
Workflow 3: Send a document using a template
Use this workflow when the document structure, fields, and signer roles are pre-configured as a template in Sadq.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Authenticate | POST /Authentication/Authority/Token | Get a Bearer token |
| 2 | Create from template | POST /api/v1/envelopes/initiate-by-template | Pass templateId — document structure applied automatically |
| 3 | Invite signer(s) | POST /api/v3/invitations | Send invitations |
| 4 | Receive result | Webhook or GET /api/v1/envelopes/{id}/status | Track completion |
| 5 | Download signed PDF | GET /api/v1/documents/{id}/signed | Download the signed document |
Workflow 4: Upload and invite in a single call
Use this shortcut workflow to combine upload and invitation into one API call. Ideal for simple, single-document signing flows.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Authenticate | POST /Authentication/Authority/Token | Get a Bearer token |
| 2 | Upload + invite | POST /api/v1/envelopes/bulk/initiate-and-invite | Upload the PDF and send invitations in one call |
| 3 | Receive result | Webhook or GET /api/v1/envelopes/{id}/status | Track completion |
| 4 | Download signed PDF | GET /api/v1/documents/{id}/signed | Download the signed document |
Workflow 5: Handle a signer who has not signed yet
Use this workflow to follow up with a signer who received the invitation but has not completed signing.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Check status | GET /api/v1/envelopes/{envelopeId}/status | Confirm which signers are still pending |
| 2a | Send a reminder | POST /api/v1/invitations/reminders/send | Send a one-time reminder to the pending signer |
| 2b | Extend expiry | PUT /api/v1/invitations/extend | Extend the link with a new availableTo date |
Note: Steps 2a and 2b are independent — you can do either or both depending on the situation.
Workflow 6: Cancel a signing request
Use this workflow to stop a signing process that is no longer needed. Cancellation is irreversible.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Check status | GET /api/v1/envelopes/{envelopeId}/status | Confirm the envelope is still active |
| 2 | Cancel | POST /api/v1/envelopes/{envelopeId}/cancel | Cancel all pending signing links |
Workflow 7: Set up webhook notifications
Use this workflow to configure Sadq to automatically notify your server when signing completes or is rejected. Set this up once before sending any signing requests.
| Order | Step | API Call | What It Does |
|---|---|---|---|
| 1 | Authenticate | POST /Authentication/Authority/Token | Get a Bearer token |
| 2 | Register webhook | POST /api/v1/webhooks | Register your server URL — save the returned id |
| 3 | Use webhookId | Pass webhookId in initiate-base64 body | Link each envelope to your webhook |
| 4 | Receive callback | Your server receives POST from Sadq | Sadq posts status, signed files, and signer details |
Which workflow should I use?
| If you want to... | Use workflow |
|---|---|
| Send one PDF to one or more signers | Workflow 1 |
| Send multiple PDFs to sign together | Workflow 2 |
| Sign using a pre-built document template | Workflow 3 |
| Upload and invite in the fewest possible API calls | Workflow 4 |
| Remind or unblock a signer who has not signed | Workflow 5 |
| Cancel a signing request that is no longer needed | Workflow 6 |
| Receive automatic notifications when signing completes | Workflow 7 |
Environments
| Environment | Base URL | Usage |
|---|---|---|
| Sandbox | https://sandbox-api.sadq-sa.com | Development & testing |
| Production | https://api.sadq-sa.com | Live environment |
API Workflow
Follow these steps in order. Steps marked OPTIONAL can be skipped depending on your implementation.
OPTIONAL — Register a Webhook (One-time setup)
Register your server endpoint once. Sadq will POST the signed file and full signer details to it automatically when signing completes. Skip this if you prefer to poll the status endpoint instead.
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/v1/webhooks | Register a single webhook URL |
| POST | /api/v1/webhooks/bulk | Register multiple webhook URLs at once |
| GET | /api/v1/webhooks | List all registered webhooks |
| PUT | /api/v1/webhooks | Update an existing webhook |
| GET | /api/v1/webhooks/logs | View delivery logs |
| POST | /api/v1/webhooks/recall | Retry a failed webhook delivery |
Request body — POST /api/v1/webhooks
| Field | Required | Description |
|---|---|---|
| webhookUrl | Yes | Your HTTPS endpoint URL that will receive the POST callback |
| headerToken | No | Auth header value Sadq will include when calling your endpoint |
| isDefault | No | If true, this webhook is used for all envelopes by default |
Note: The
idreturned in the response is yourwebhookId. Save it — you will pass it in the Initiate Envelope call.
STEP 1 — Authenticate — Get Bearer Token
Call this before any other API. Send credentials as application/x-www-form-urlencoded with Basic Auth header. The returned JWT is valid for approximately 27.5 hours (99,200 seconds). Include it as Authorization: Bearer <token> on every subsequent request.
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /Authentication/Authority/Token | Obtain JWT Bearer token |
Request fields
| Field | Required | Description |
|---|---|---|
| grant_type | Yes | Always set to "integration" |
| username | Yes | Your integration username or email |
| password | Yes | Your integration password |
| accountId | Yes | Your Sadq Account ID (GUID format) |
| accountSecret | Yes | Your account secret key |
Response fields
| Field | Description |
|---|---|
| access_token | JWT Bearer token — include in all subsequent request headers |
| expires_in | Expiry in seconds (99,200 = ~27.5 hours) |
| token_type | Always "Bearer" |
| useraccessKey | Private key — store securely, never expose in logs or client code |
STEP 2 — Initiate Envelope — Upload the Document
Upload your PDF document to create an envelope. The response returns a documentId and envelopeId that you will use in the next step.
| Method | Endpoint | Use When |
|---|---|---|
| POST | /api/v1/envelopes/initiate-base64 | Sending a single PDF as a Base64 JSON string |
| POST | /api/v1/envelopes/initiate | Uploading a single PDF as multipart/form-data |
| POST | /api/v1/envelopes/bulk/initiate-base64 | Uploading multiple PDFs in one envelope |
| POST | /api/v1/envelopes/initiate-by-template | Using a pre-built template (pass templateId) |
| POST | /api/v1/envelopes/{envelopeId}/files | Adding more files to an existing envelope |
Request fields (initiate-base64)
| Field | Required | Description |
|---|---|---|
| files.file | Yes | Base64-encoded PDF content |
| files.fileName | Yes | Name of the PDF file |
| userOnlySigner | Yes | Set true if only the account owner will sign |
| webhookId | No | ID of a registered webhook to notify on completion |
| workflowId | No | Link to a predefined signing workflow |
| referenceNumber | No | Your own tracking reference (auto-generated if omitted) |
Response fields
| Field | Description |
|---|---|
| data.documentId | Unique ID for the document — use this in Send Invitation |
| data.envelopeId | Unique ID for the envelope |
| data.referenceNumber | Your reference number |
| errorCode | 0 = success, non-zero = error |
STEP 3 — Send Invitations — Notify Signers
Define who should sign the document, how they authenticate, and where their signature appears. Sadq sends the signing link by email and/or SMS depending on which contact fields you provide.
Note: At least one of
destinationEmailordestinationPhoneNumberis required per signer.
| Method | Endpoint | Key Difference |
|---|---|---|
| POST | /api/v1/invitations | Standard — by documentId. Sadq sends email/SMS. No link in response. |
| POST | /api/v2/invitations | Returns invitationLink in response. No email/SMS sent. |
| POST | /api/v3/invitations | Best of both — Sadq sends email/SMS AND returns invitationLink. |
| POST | /api/v1/invitations/envelope | By envelopeId — use when envelope has multiple documents. |
| POST | /api/v1/invitations/bulk/send | Send to multiple documents in a single API call. |
Destination object — per signer
| Field | Required | Description |
|---|---|---|
| destinationName | Yes | Full name of the recipient |
| destinationEmail | One of | Email address — signing link sent by email |
| destinationPhoneNumber | One of | Phone number — signing link sent by SMS |
| signeOrder | Yes | Signing sequence: 1, 2, 3... |
| authenticationType | No | Identity verification method (see Authentication Types below) |
| destinationType | No | 1 = Signer, 3 = CC (copy), 4 = Reviewer |
| consentOnly | No | true = click-to-agree, no drawn signature required |
| nationalId | No | Required when authenticationType is Nafath |
| availableTo | No | Link expiry date/time in ISO 8601 format |
| redirectUrl | No | URL to redirect signer to after completing signing |
| invitationLanguage | No | 0 = Arabic, 1 = English |
| allowUserToSignAnyWhere | No | true = signer can place signature freely on the document |
| dailyNotify | No | true = send daily email reminders until signed |
| signatories | Conditional | Array of signature field positions (required if consentOnly is false) |
Authentication types
| Value | Name | Description |
|---|---|---|
| 0 | None | No identity verification required |
| 1 | Nafath KYC | First-time Nafath verification, then Sadq credentials |
| 2 | SMS OTP | One-time password sent via SMS |
| 3 | Email OTP | One-time password sent via email |
| 5 | Digital Sign | Digital signature authentication |
| 7 | Nafath App | Push authentication via the Nafath mobile app (every time) |
| 9 | Absher OTP | OTP via the Absher platform |
| 10 | OTP sent via WhatsApp |
Signatory object — signature field placement
| Field | Required | Description |
|---|---|---|
| type | Yes | Signature / initial / stamp / signDate / TextField / radio / checkbox |
| positionX | Yes | X coordinate on the page (PDF units from bottom-left) |
| positionY | Yes | Y coordinate on the page (PDF units from bottom-left) |
| signatureWidth | Yes | Width of the signature box in PDF units |
| signatureHigh | Yes | Height of the signature box in PDF units |
| pageNumber | Yes | Page number where the signature appears (1-based) |
| isRequired | No | Whether the field must be filled by the signer |
| appendDate | No | Automatically append the signing date next to the signature |
OPTIONAL — Shortcut: Initiate + Invite in One Call
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /api/v1/envelopes/bulk/initiate-and-invite | Upload + send invitations in a single API call |
Supports SaveAsDraft: true to create the envelope without sending invitations yet.
STEP 4 — Track Signing Status
Option A — Webhook (recommended)
Sadq automatically POSTs to your registered URL when all signers complete or reject. The signed PDF is included as Base64 in the payload — no separate download call needed.
Webhook payload structure
| Field | Type | Description |
|---|---|---|
| RequestId | GUID | Your original requestId from the initiate call |
| Status | Integer | 1 = Completed, 2 = Rejected |
| ReferencNumber | String | Your reference number |
| Files[].FileName | String | Name of the signed PDF file |
| Files[].File | String | Signed PDF as Base64 — save directly |
| Signatory[].Status | String | SIGNED or REJECTED per signer |
| Signatory[].FullName | String | Signer full name (English) |
| Signatory[].FullNameAr | String | Signer full name (Arabic) |
| Signatory[].NationalId | String | National ID (populated for Nafath-verified signers) |
| Signatory[].AuthenticationType | String | e.g. NAFATH, SADQLOGIN, WITHOUTVALIDATION |
| Signatory[].Gender | String | MALE or FEMALE |
| Signatory[].RejectReason | String | Rejection reason text (null if signed) |
Option B — Poll envelope status
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/v1/envelopes/{envelopeId}/status | Get current signing status and per-signer progress |
Possible status values: Pending, In Progress, Completed, Rejected, Cancelled, Expired
STEP 5 — Download the Signed Document
If you used a webhook, the signed file is already in the Files[] array of the payload and no download call is needed.
| Method | Endpoint | Returns |
|---|---|---|
| GET | /api/v1/documents/{id}/signed | Signed PDF as binary file download |
| GET | /api/v1/documents/{id}/completed/base64 | Signed PDF as Base64 JSON — single file |
| GET | /api/v1/envelopes/{envelopeId}/files/completed | All completed files in the envelope as Base64 array |
Lifecycle Management
Extend invitation expiry
| Method | Endpoint | Use When |
|---|---|---|
| PUT | /api/v1/invitations/extend | Extending one specific signer's link — pass destinationId |
| PUT | /api/v1/envelopes/extend-invitations | Extending all signers at once — pass envelopeId |
Send reminders
| Method | Endpoint | Use When |
|---|---|---|
| POST | /api/v1/invitations/reminders/send | Sending a reminder to a single signer |
| POST | /api/v1/invitations/bulk/reminders/send | Sending reminders to multiple signers in one call |
Cancel envelope
| Method | Endpoint | Notes |
|---|---|---|
| POST | /api/v1/envelopes/{envelopeId}/cancel | Cancels all pending signing links. Irreversible. |
Error Codes
Every API response includes an errorCode field. A value of 0 indicates success.
| Code | Name | Description |
|---|---|---|
| 0 | Success | Operation completed successfully |
| 1 | SessionTimeOut | The session has expired — re-authenticate |
| 3 | UnAuthorized | Token missing or does not have permission |
| 4 | InvalidUserNameOrPassword | Credentials are incorrect |
| 8 | ValidationError | Request body failed validation — check required fields |
| 9 | BadRequest | Malformed or invalid request |
| 10 | InvalidFileIdOrRequestId | Provided file ID or request ID does not exist |
| 14 | UnauthorizedRequest | Request is not authorized for this account |
| 16 | ContentIsEmpty | Request body content is empty |
| 21 | SignFailed | The document signing process failed |
| 24 | DisabledAccount | The account is disabled |
| 28 | ExceededAccountTransactionQuota | Account transaction quota exceeded |
| 100 | GeneralError | Unexpected server-side error |
| 102 | PasswordProtectedFile | Uploaded PDF is password-protected |
| 134 | InvalidWebhookUrl | The webhook URL is not reachable or invalid |
Quick Reference
| Method | Endpoint | Step | Purpose |
|---|---|---|---|
| POST | /api/v1/webhooks | Setup | Register webhook |
| POST | /Authentication/Authority/Token | 1 | Get Bearer token |
| POST | /api/v1/envelopes/initiate-base64 | 2 | Upload PDF (Base64) |
| POST | /api/v1/envelopes/initiate | 2 | Upload PDF (multipart) |
| POST | /api/v1/envelopes/bulk/initiate-base64 | 2 | Upload multiple PDFs |
| POST | /api/v1/envelopes/initiate-by-template | 2 | Upload via template |
| POST | /api/v1/invitations | 3 | Invite by documentId (v1) |
| POST | /api/v2/invitations | 3 | Invite — returns link only |
| POST | /api/v3/invitations | 3 | Invite — returns link + notifies |
| POST | /api/v1/invitations/envelope | 3 | Invite by envelopeId |
| POST | /api/v1/invitations/bulk/send | 3 | Bulk invite |
| POST | /api/v1/envelopes/bulk/initiate-and-invite | 2+3 | Upload + invite in one call |
| GET | /api/v1/envelopes/{envelopeId}/status | 4 | Poll signing status |
| GET | /api/v1/documents/{id}/signed | 5 | Download signed PDF (binary) |
| GET | /api/v1/documents/{id}/completed/base64 | 5 | Download as Base64 |
| GET | /api/v1/envelopes/{id}/files/completed | 5 | All envelope files |
| PUT | /api/v1/invitations/extend | Mgmt | Extend single signer expiry |
| PUT | /api/v1/envelopes/extend-invitations | Mgmt | Extend all signers expiry |
| POST | /api/v1/invitations/reminders/send | Mgmt | Send reminder |
| POST | /api/v1/invitations/bulk/reminders/send | Mgmt | Bulk send reminders |
| POST | /api/v1/envelopes/{envelopeId}/cancel | Mgmt | Cancel envelope |