CM Sign offers the ability to have end users sign PDF documents online. You can use the CM webapplication or, if you want an integration with your own systems, request access to our API.
Before starting integration of CM Sign into your services, we advise you to read our implementation guide. This guide can be used for a step-by-step implementation of CM Sign.
Download: implementation guide (PDF)
For a full API specification with parameter formats, a Swagger specification is available.
If you need technical assistance, please contact [email protected]
A dossier is a collection of information related to the signing process of a document. Dossiers consist of:
A dossier automatically expires after 30 days by default, this can be customised when creating the dossier (up to 90 days).
Invitees are persons asked to sign a specific dossier. An invitee has:
Fields are locations within a PDF document where information will be added. Fields belong to a specific file and invitee and have parameters to configure its position(s) in the document.
The following field types are supported:
signature
: the invitee is asked for a signaturesignatureDate
: the date the invitee signed the document, automatically determinedinitials
: the invitee is asked for its initials. Initials can be specified for a page range and the invitee has to confirm its initials each page.text
: a text field that can be filled in by the inviteelabel
: a text field that contains a predefined text which cannot be modifiedcheckbox
: a box which can be checked by the userradio
: a group of radio buttons, of which one option must be selectedstamp
: the invitee is asked for its stamp/seal (hanko), mostly used in AsiaAn invite is a unique URL for each invitee to view the dossier. CM Sign can email these invites to the invitees or you can distribute the URL yourself, for example by redirecting or sending customised emails yourself.
An invite can have a custom expiration time, specified during creation. Creating multiple invites for an invitee is possible and this might be required if an invite expires before the invitee signed the document.
CM Sign provides two environments:
https://api.sandbox.cmdisp.com/sign/v1/
https://api.cmdisp.com/sign/v1/
The sandbox environment is ideally suited to do your initial experimentation with. Unlike the production environment, it doesn't add a cryptographic signature to the document and you will not be billed for using the sandbox environment.
Please note that the credentials for sandbox and production environment are different.
The steps for using the service are roughly:
Before you can start using the API, you need API credentials. These consist of a Key and a Key ID and can be obtained by registering for CM Sign. This will grant you access to the sandbox environment.
The credentials provided by CM are confidential and 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 like:
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
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 at which the token is generated
nbf
: the time after which the token is valid
exp
: the time after which 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 a token.
Every dossier is started with at least one file, the first step is to upload your PDF.
POST https://api.cmdisp.com/sign/v1/upload
Content-Type: multipart/form-data
Authorization: Bearer GENERATED_TOKEN_HERE
curl -X POST \
https://api.cmdisp.com/sign/v1/upload \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjNiNDM4NDM3LTA0YTQtNDBiYi04Mzg5LTU0YmIwMjc2NmZiYSJ9.eyJpYXQiOjE1NDYzMDA4MDAsIm5iZiI6MTU0NjMwMDgwMCwiZXhwIjoxNTQ2MzAwODYwfQ.bwqCUHS1d5d8guAPHDsdd9-a8oXxH1q45O0tDP1asTo' \
-H 'content-type: multipart/form-data' \
-F '[email protected]/tmp/Document.pdf'
This is a multipart/form-data
request where the file
parameter is the key for the file to be uploaded.
{
"id": "3fa4ddab-56a4-48bb-9072-8a61b422ea82",
"name": "Document",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"contentType": "application/pdf",
"derivativeOf": null,
"uploadDateTime": "2019-01-01T00:00:00+00:00"
}
The result of this request is a JSON response containing a description of the file as registered within CM Sign. The most important attribute in this response is the id
. This id
is the unique identifier for this file to be passed along when creating the actual 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 view and sign or review the document.
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 and multiple owners can be specified.
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. 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 the you can sign the document. You can set readOnly
to true
on invitee that needs to review the document.
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 making it white.
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 were sent by CM Sign.
POST https://api.cmdisp.com/sign/v1/dossiers
Content-Type: application/json
Authorization: Bearer GENERATED_TOKEN_HERE
{
"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
}
]
}
{
"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": "2019-01-01T00:00:00+00:00"
}
],
"invitees": [
{
"id": "f6d1afd5-aa6a-4c5e-8348-bf5a5310b5d2",
"name": "Invitee",
"email": "[email protected]",
"phoneNumber": null,
"identificationMethod": null,
"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": "2019-01-31T00:00:00+00:00",
"createdAt": "2019-01-01T00:00:00+00:00"
}
Once you have a complete dossier, you will have to send out a link to the invitees who will have to sign these documents. CM Sign can send emails automatically if you set email
to true
. If you don't set the email option, the link can be retrieved from the response of the request. 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.
POST https://api.cmdisp.com/sign/v1/dossiers/{dossierId}/invites
Content-Type: application/json
Authorization: Bearer GENERATED_TOKEN_HERE
[
{
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"email": true,
"expiresIn": 2592000
}
]
[
{
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"email": true,
"expiresIn": 2592000,
"emailConfig": {
"message": "Custom message here"
}
}
]
[
{
"id": "22b33b45-bde6-45f4-a45a-ec1fa53ffffa",
"inviteeId": "80692813-3493-40e9-86c3-d3b6f7378929",
"inviteUri": null,
"readOnly": false,
"identificationMethod": null,
"email": true,
"reminder": false,
"emailSentAt": "2019-01-01T00:00:00+00:00",
"expiresIn": 2592000,
"expiresAt": "2019-01-31T00:00:00+00:00",
"createdAt": "2019-01-01T00:00:00+00:00"
}
]
A webhook URL can be configured for your Key ID so you get notified about status updates for the dossier.
Please contact [email protected] and tell us your Key ID and the URL that needs to be configured.
POST https://yourwebserver
Content-Type: application/json
{
"id": "b041a287-bc92-4469-801e-ae1a39c08f6e",
"type": "dossier.state.updated",
"dossier": {
"id": "b659c273-954e-43cf-893a-0f74a7f87153",
"state": "completed"
},
"created": "2019-01-01T00:00:00+00:00"
}
The status code should be in the 2xx range (between 200 and 300), the response body doesn't matter as it's ignored. In case of an unsuccessful status code (4xx, 5xx), the webhook will be retried.
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.
To download the signed document, specifying the type=file
query parameter.
GET https://api.cmdisp.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.cmdisp.com/sign/v1/dossiers/{dossierId}/download?type=file&file=8d817359-7eb8-4b6e-9030-17ac286b7dc0
The audit report contains all info and events related to the dossier for evidence purposes, specify the type=auditReport
query parameter.
GET https://api.cmdisp.com/sign/v1/dossiers/{dossierId}/download?type=auditReport
The ZIP file contains all signed documents and the audit report.
GET https://api.cmdisp.com/sign/v1/dossiers/{dossierId}/download
When an error occurs, you will receive a JSON message describing the error. Please make sure to handle these errors.
Example:
{
"status": 400,
"message": "Error message"
}
For a complete technical documentation with specifications for all field types, JSON objects and methods, you can consult our complete swagger specification.