Digital Signing API
The Digital Signing API creates signing orders from your own system and follows them until the documents are signed. For the application, read Digital Signing.
Every call needs a bearer token, see Authentication, and a company that has the signing licence. The orders belong to your own company.
https://api.digitalsigning.metaforce.net/DigitalSigningOrders
Property names in requests and responses are written in camel case, for example packageName.
Check before you create
GET /DigitalSigningOrders/GetCreateOrderInitialData/{langCode} returns what you need to prepare an order. langCode is optional and picks the language of the default texts. The response has:
| Field | What it is |
|---|---|
isCreateNewOrderAvailable | Whether your company can create an order now. |
orderAvailabilityMessage | Why not, when it cannot. |
emailSigningSubject, emailSigningMessage | The default email text. |
providerSigningSubject, providerSigningMessage | The default text shown when signing. |
providerType, archiveType | The signing provider and the archive in use. |
availableFolders | The Archive folders you can use for archiveFolderId. |
languages | The languages you can pick. |
Create an order
POST /DigitalSigningOrders takes a JSON body.
| Field | What it is |
|---|---|
signatories | The people who sign. At least one. See below. |
signingOrderFiles | The PDF files to sign, one to ten, each with a name and the file as a base64 fileContent. |
packageName | The name of the order. Required. |
language | The language of the notifications and the signing page. Required. One of cs, da, de, el, en, es, et, fi, fr, hu, is, it, lt, lv, nb, nl, pl, pt or sv. |
emailNotificationSubject, emailNotificationMessage | The subject (up to 256 characters) and text (up to 8000 characters) of the email to each signatory. Required. |
signingNotificationTitle, signingNotificationMessage | The title (up to 256 characters) and text (up to 8000 characters) shown when signing. Required. |
useSignatureOrder | Sign in a fixed order. Use it together with signingSequence on each signatory. |
signNowViaUrl | Give each signatory a link to sign at once. |
completedWebhookUrl, cancelledWebhookUrl | URLs Doc Gen calls when the order is completed or cancelled. See Webhooks. |
distributeSignedDocumentToAllSignatories | Send the signed document to every signatory. |
archiveFolderId | The Archive folder to store the signed documents in. |
Each signatory has:
| Field | What it is |
|---|---|
id | Optional. Your own identifier for the signatory, up to 64 characters of letters, digits, - and _. |
emailAddress | Where to send the request. Required. |
firstName, lastName | The name. Some signing providers require them. |
personalNumber | The personal number, for providers that check it. A number the provider rejects is reported as invalid_personal_number. |
signViaUrl | Give this signatory a link to sign at once. |
signingSequence | Initial, DependsOnInitial or NoOrder. |
signUrl | Send an empty string. Doc Gen fills it in, but the request is rejected with 400 if the field is missing. |
{
"packageName": "Employment contract, Ingrid Berg",
"language": "en",
"emailNotificationSubject": "Please sign your employment contract",
"emailNotificationMessage": "Hi Ingrid, your employment contract is ready to sign.",
"signingNotificationTitle": "Employment contract",
"signingNotificationMessage": "Read the contract and sign it.",
"signatories": [
{
"emailAddress": "ingrid.berg@example.com",
"firstName": "Ingrid",
"lastName": "Berg",
"signingSequence": "Initial",
"signUrl": ""
}
],
"signingOrderFiles": [
{ "name": "contract.pdf", "fileContent": "JVBERi0xLjQK..." }
],
"completedWebhookUrl": "https://example.com/signing/completed"
}A request that misses a required field is answered with 400. The call answers 200 when the request is valid, so read the body. It has data, type and message. type is 0 when the order was created, 1 when it could not be created and 2 when the licence stopped it. On success, data holds the order and its id.
These messages can come back:
type | message | Meaning |
|---|---|---|
| 1 | invalid_personal_number | The signing provider rejected a personal number. |
| 1 | something_went_wrong_with_external_provider | The signing provider could not create the order. |
| 1 | something_went_wrong_internal | A signatory has no firstName or lastName while your signing provider shows names, or the order could not be saved. With such a provider, send both names for every signatory. |
| 2 | licence_order_will_exceed_usage | This order would take your company over its licence. |
| 2 | Another licence message | Your licence does not allow new orders at the moment. |
Follow an order
| Call | What it returns |
|---|---|
POST /DigitalSigningOrders/GetListOfOrders | The most recent orders that match your search. All fields are optional: fromDate, toDate, fileStatus (a list of order statuses), sortBy and sortDesc. |
GET /DigitalSigningOrders/{id} | One order with its files and signatories. 404 if it does not exist. |
GET /Activities | The newest five orders that changed. |
An order has a status. In responses it is a number:
| Number | Status |
|---|---|
| 1 | Created |
| 5 | InProgress |
| 10 | Completed |
| 20 | DownloadedFromSigningProvider |
| 50 | Rejected |
| 70 | Canceled |
| 99 | Error |
Each signatory has a signStatus as well, and a signingSequence (0 for Initial, 1 for DependsOnInitial, 2 for NoOrder). The sign status goes from not set (0) and created (1) through started (2) to completed (3), rejected (4), expired (5), forwarded (6) or canceled (7).
Get the files
| Call | What it returns |
|---|---|
GET /DigitalSigningOrders/GetCertifiedPdf/{orderId} | The signed files. Works for completed orders only. |
GET /DigitalSigningOrders/GetPdfFromProvider/{orderId} | The signed files as held by the signing provider. Works for completed orders only. |
GET /DigitalSigningOrders/GetSignatureFile/{orderId}/{signatureId} | The proof of one signature, for providers that supply one. |
GET /DigitalSigningOrders/GetAllSignatureFiles/{orderId} | The proof of every signature on every document. |
A file that does not exist is answered with 404.
Remind, cancel and delete
GET /DigitalSigningOrders/SendReminders/{orderId}sends an email to every signatory who has not signed yet.DELETE /DigitalSigningOrders/{orderId}cancels the order.DELETE /DigitalSigningOrders/DeleteOrder/{orderId}deletes the order.
Each of these answers true or false in the body.
Webhooks
When the order is completed, Doc Gen calls completedWebhookUrl. When it is cancelled, Doc Gen calls cancelledWebhookUrl. The call is a GET without a body, so use it as a signal and then fetch the order with GET /DigitalSigningOrders/{id}. If Doc Gen cannot reach the URL, it tries again, up to four attempts in all, about half a second apart. An answer with an error status is not tried again.
Example
const axios = require('axios').default;
async function createOrder(accessToken) {
const response = await axios({
method: 'POST',
url: 'https://api.digitalsigning.metaforce.net/DigitalSigningOrders',
headers: {
'content-type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
data: {
packageName: 'Employment contract, Ingrid Berg',
language: 'en',
emailNotificationSubject: 'Please sign your employment contract',
emailNotificationMessage: 'Hi Ingrid, your employment contract is ready to sign.',
signingNotificationTitle: 'Employment contract',
signingNotificationMessage: 'Read the contract and sign it.',
signatories: [
{ emailAddress: 'ingrid.berg@example.com', firstName: 'Ingrid', lastName: 'Berg', signUrl: '' }
],
signingOrderFiles: [
{ name: 'contract.pdf', fileContent: '<base64 of the PDF>' }
]
}
});
console.log(response.data.type, response.data.message);
}