Getting started
The steps for using the service are:
- Upload one or more PDF documents that need to be signed
- Create a dossier which references these documents. A dossier includes information about the end users who need to sign the document, as well as the location within the PDF document(s) where they need to place their signature and/or initials.
- Create an invite for each invitee to sign/review the document
- The end user is directed to the invite URL, for example via email
- The end user is presented a web interface where he can read and sign or review and approve the document
- The dossier owner is notified of the completion of the dossier
- Retrieve the signed document and audit report after receiving the webhook notification
Authentication
Before you can start using the API, you need API credentials. Credentials consist of a key ID and secret. They can be obtained by registering for the Sign API, this will grant you access to the sandbox environment. Contact your account manager to get production credentials. Credentials should be kept secret.
In order to authenticate you need to use your credentials to generate a JWT Bearer token. The JWT token has to be generated using the HS256
algorithm and your credentials. This JWT has to contain the following attributes: iat
, nbf
, exp
in the payload, as well as the attribute kid
in the header of the JWT. This kid
attribute needs to contain the Key ID of your credentials.
The generated token needs to be passed via the HTTP Authorization header:
Authorization: Bearer GENERATED_TOKEN_HERE
There are many libraries available for different programming languages that can help you to generate a JWT. See the Libraries tab on https://jwt.io.
Example
Assuming we want to create a token that is valid for 60 seconds and we have received the following credentials:
Key ID: 3b438437-04a4-40bb-8389-54bb02766fba
Secret: AC4Etykn7jusGR5FwLDAtILtQbiQbTMKedP31szXg4WlSbjGEXyNMZ
We need to create a JWT with the following properties:
JWT header:
{
"alg": "HS256",
"typ": "JWT",
"kid": "3b438437-04a4-40bb-8389-54bb02766fba"
}
JWT payload:
{
"iat": 1546300800,
"nbf": 1546300800,
"exp": 1546300860
}
iat
: the time when the token was generatednbf
: the time after which the token is valid, usually equal toiat
exp
: the time when the token will expire
Make sure these are UNIX timestamps in seconds
This results in the following token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjNiNDM4NDM3LTA0YTQtNDBiYi04Mzg5LTU0YmIwMjc2NmZiYSJ9.eyJpYXQiOjE1NDYzMDA4MDAsIm5iZiI6MTU0NjMwMDgwMCwiZXhwIjoxNTQ2MzAwODYwfQ.bwqCUHS1d5d8guAPHDsdd9-a8oXxH1q45O0tDP1asTo
Add this token to the Authorization
header in the API request.
Authorization: Bearer GENERATED_TOKEN_HERE
The https://jwt.io website provides a way to inspect or validate JWT tokens.
Upload a document
Every dossier requires at least one file, the first step is to upload your PDF document.
POST https://api.cm.com/sign/v1/upload
This is a multipart/form-data
request where the file
parameter is the key for the file to be uploaded.
Request headers
Content-Type: multipart/form-data
Authorization: Bearer GENERATED_TOKEN_HERE
Example
curl -X POST \
https://api.cm.com/sign/v1/upload \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjNiNDM4NDM3LTA0YTQtNDBiYi04Mzg5LTU0YmIwMjc2NmZiYSJ9.eyJpYXQiOjE1NDYzMDA4MDAsIm5iZiI6MTU0NjMwMDgwMCwiZXhwIjoxNTQ2MzAwODYwfQ.bwqCUHS1d5d8guAPHDsdd9-a8oXxH1q45O0tDP1asTo' \
-H 'content-type: multipart/form-data' \
-F 'file=@/tmp/Document.pdf'
Response
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"name": "Document",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"contentType": "application/pdf",
"derivativeOf": null,
"uploadDateTime": "2022-01-01T00:00:00+00:00"
}
The response of this request contains a description of the file as registered within Sign. The most important attribute in this response is the file id
. This id
is the unique identifier for this file to be passed along when creating the actual dossier.
Create a dossier
A dossier is the primary container for all information regarding the documents to be signed. It contains the file(s) to be signed, the invitees who will be invited to sign or review the document.
Owners
Owners receive status updates about the dossier, for example when a dossier has been signed by one of the invitees, and receive the audit report when the dossier has been completed. Owners are optional, multiple owners can be specified.
More info: dossiers
Invitees
To define a sign order, set the position
attribute on an invitee. For example, if there are two invitees, set position 1
for the first invitee and position 2
for the second invitee. This way, the second invitee will only receive his invite after the first invitee has signed. It is possible to set multiple invitees on the same position.
Make sure the positions are consecutive and there is no gap between them.
Sometimes you want a dossier to be reviewed and approved (without signing it) by someone before you can sign the document. You can set readOnly
to true
on invitee that needs to review the document.
More info: invitees
Fields
For each field, you have to pass the id of the file on which the field will be placed. With the unit point
, the locations of fields are determined using 72 DPI. The coordinates are from top-left to bottom-right.
Next to supplying locations, the location can also be automatically determined based on a tag
. The tag acts as a placeholder; the range and location of the field will be determined based on the location(s) of the tag in the document. In case of initials, add the tag to every page the field should be added to. The tag should be hidden, for example, by setting the text color to white.
Fields and field locations can also be determined by using the web interface of Sign. To use this feature set prepare: true
in the POST
request to /dossiers
. The response will contain the prepareUrl
field. This URL is valid for 60 minutes. Open this URL in the browser, add fields to the invitees and submit the page. After the page is submitted the user is shown a success page or you can redirect to your own page by providing prepareReturnUrl
to the dossier request. If you use webhooks then you can also enable the dossier.prepared
event to be sent.
More info: fields
Reminders
To increase conversion, it's recommended to use automatic reminders. Automatic reminders can be enabled by specifying the reminderIn
field. Its value is the time in seconds after the invite was sent to an invitee, after which the reminder will be sent. Reminders only work if the invite emails, SMS or WhatsApp Business Platform notifications were sent by Sign.
Request
POST https://api.cm.com/sign/v1/dossiers
Request headers
Content-Type: application/json
Authorization: Bearer GENERATED_TOKEN_HERE
Request body
Example with field points, tags
{
"name": "Purchase contract",
"files": [
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82"
}
],
"reminderIn": 604800,
"invitees": [
{
"name": "Invitee",
"email": "[email protected]",
"position": 1,
"locale": "nl-NL",
"fields": [
{
"type": "signature",
"file": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"locations": [
{
"range": "1",
"unit": "point",
"x": 500,
"y": 750,
"width": 100,
"height": 50
}
]
},
{
"type": "initials",
"file": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"tag": "{init1}"
},
{
"type": "initials",
"file": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"tag": "{optionalTag}",
"tagRequired": false
}
]
}
],
"owners": [
{
"name": "Owner",
"email": "[email protected]"
},
{
"name": "Owner Copy",
"email": "[email protected]",
"cc": true
}
]
}
Response
{
"id": "302935b2-8a22-4e25-bffb-fccda8963bd4",
"name": "Purchase contract",
"state": "draft",
"locale": "en-US",
"completed": false,
"reminderIn": 604800,
"owners": [
{
"id": "0474a0f6-0901-4ca1-810d-01ea8c830c97",
"name": "Owner",
"email": "[email protected]",
"cc": false
},
{
"id": "3a4f3799-4480-4d07-945a-e4e96fd51e4e",
"name": "Owner Copy",
"email": "[email protected]",
"cc": true
}
],
"files": [
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"name": "Document",
"hash": "a497a1df892b6d2f205460b730b09c3a00c366061fa8975a388ce9672a39e833",
"contentType": "application/pdf",
"derivativeOf": null,
"uploadDateTime": "2022-01-01T00:00:00+00:00"
}
],
"invitees": [
{
"id": "f6d1afd5-aa6a-4c5e-8348-bf5a5310b5d2",
"name": "Invitee",
"email": "[email protected]",
"phoneNumber": null,
"authenticationMethods": [],
"identificationMethods": [],
"reference": null,
"readOnly": false,
"state": null,
"stateChanged": null,
"position": null,
"locale": "nl-NL",
"fields": [
{
"id": "a4542a27-5f93-483e-910d-a520770c9444",
"type": "signature",
"tag": null,
"file": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"invitee": "f6d1afd5-aa6a-4c5e-8348-bf5a5310b5d2",
"locations": [
{
"range": "1",
"unit": "point",
"x": 500,
"y": 750,
"width": 100,
"height": 50
}
]
},
{
"id": "7ead6deb-962a-475c-8a9f-c764b7e55357",
"type": "initials",
"tag": "{init1}",
"file": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"invitee": "f6d1afd5-aa6a-4c5e-8348-bf5a5310b5d2",
"locations": [
{
"range": "1-3",
"unit": "point",
"x": 341.2251,
"y": 775.2541,
"width": 30.0294,
"height": 30.0294
}
]
}
]
}
],
"expiresIn": 2592000,
"expiresAt": "2022-01-31T00:00:00+00:00",
"createdAt": "2022-01-01T00:00:00+00:00"
}
Request
Field placement via web interface.
Request body
{
"name": "Purchase contract",
"files": [
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82"
}
],
"invitees": [
{
"name": "Invitee",
"email": "[email protected]",
"position": 1,
"locale": "nl-NL"
}
],
"reminderIn": 604800,
"prepare": true,
"prepareReturnUrl": "https://example.com"
}
Response
{
"id": "abb39845-421b-479a-a384-2e07580c0f0b",
"name": "Purchase contract",
"state": "draft",
"locale": "en-US",
"completed": false,
"owners": [],
"files": [
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"name": "Document",
"hash": "a497a1df892b6d2f205460b730b09c3a00c366061fa8975a388ce9672a39e833",
"contentType": "application/pdf",
"derivativeOf": null,
"uploadDateTime": "2022-01-01T00:00:00+00:00"
}
],
"invitees": [
{
"id": "51b45bd2-5a1a-4375-9799-a19c58fa9924",
"name": "Invitee",
"email": "[email protected]",
"phoneNumber": null,
"authenticationMethods": [],
"identificationMethods": [],
"reference": null,
"readOnly": false,
"state": null,
"stateComment": null,
"stateChanged": null,
"position": 1,
"locale": "nl-NL",
"redirectUrl": null,
"fields": []
}
],
"reminderIn": 604800,
"prepareUrl": "https://www.cm.com/app/sign/prepare/abb39845-421b-479a-a384-2e07580c0f0b?t=eyJ0eXAiOiJKV1Qi...",
"expiresIn": 2592000,
"expiresAt": "2022-01-31T00:00:00+00:00",
"createdAt": "2022-01-01T00:00:00+00:00"
}
Send invites
Once you have a complete dossier, you will have to send out a link to the invitees who will have to sign these documents. Sign can send emails automatically if you set channel
to email
. If you don't set the channel
option, the invite URL will be included in the response. In this case you have to redirect the user to the inviteUri
yourself. Invites have a configurable expiration time in seconds, the default is 30 days.
Please note if you place fields using the web interface this step first needs to complete before you can send an invite.
POST https://api.cm.com/sign/v1/dossiers/{dossierId}/invites
Request headers
Content-Type: application/json
Authorization: Bearer GENERATED_TOKEN_HERE
Request body
[
{
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"channel": "email",
"expiresIn": 2592000
}
]
Request body (with custom message)
[
{
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"channel": "email",
"emailConfig": {
"message": "Custom message here"
},
"expiresIn": 2592000
}
]
Response
[
{
"id": "22b33b45-bde6-45f4-a45a-ec1fa53ffffa",
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"inviteUri": null,
"readOnly": false,
"identificationMethod": null,
"channel": "email",
"reminder": false,
"emailSentAt": "2022-01-01T00:00:00+00:00",
"expiresIn": 2592000,
"expiresAt": "2022-01-31T00:00:00+00:00",
"createdAt": "2022-01-01T00:00:00+00:00"
}
]
Download files
Once the dossier is completed, you can download the documents.
Please note that the dossier can only be downloaded until the expiry of the dossier set by the
expiresIn
field.
Document
To download the signed document, specifying the type=file
query parameter.
GET https://api.cm.com/sign/v1/dossiers/{dossierId}/download?type=file
When there are multiple documents per dossier you will need to specify the file id.
GET https://api.cm.com/sign/v1/dossiers/{dossierId}/download?type=file&file=8d817359-7eb8-4b6e-9030-17ac286b7dc0
Audit Report
The audit report contains all info and events related to the dossier for evidence purposes, specify the type=auditReport
query parameter.
GET https://api.cm.com/sign/v1/dossiers/{dossierId}/download?type=auditReport
Full ZIP
The ZIP file contains all signed documents, attachments and the audit report.
GET https://api.cm.com/sign/v1/dossiers/{dossierId}/download
Events
To get notified when a dossier is completed or other events occurred, you can subscribe to events.
See: Events.
Error handling
When an error occurs, you will receive a JSON response describing the error. The error codes per endpoint can be found in the API reference.
Example:
{
"status": 400,
"message": "Error message"
}
Updated 8 months ago