{
  1. Introduction
    1. Service description
    2. Environments
  2. Getting started
    1. Authentication
    2. Upload document
    3. Create dossier
    4. Send invites
    5. Dossier download
  3. Events
    1. Event webhooks
    2. Subscribe to events
    3. Retrieve status callback
  4. Error handling
  5. Use cases
    1. Change language / locale
    2. Send invite using SMS
    3. Send invite using WhatsApp Business Platform
    4. Include invite in your own system
    5. Require identification
    6. Require payment
    7. Cancel a dossier
    8. Configure branding
    9. Configure invitee emails
    10. Create dossier based on a template
  6. Swagger API documentation

Introduction

Sign by CM.com is a service to have users sign PDF documents online. You can use the Sign application or, if you want an integration with your own systems, request access to our API. This documentation focuses on the API integration.

For a complete technical documentation with specifications for all field types, JSON objects and methods, you can consult our complete swagger specification: Swagger API documentation

If you need technical assistance, please contact your account manager or support ([email protected]).

Service description

Dossiers

A dossier is a collection of information related to the signing process of a document. Dossiers consist, among other things, of:

  • Files: the PDF document(s) to be signed
  • Invitees: the persons who have to sign or review the dossier
  • Owners (optional): the contact person who will be informed about status updates of the dossier
  • Attachments (optional): files attached to the dossier which doesn't have to be signed

A dossier expires after 30 days by default, this can be customised when creating the dossier (up to 90 days).

Files

Files are the PDF documents presented to the user to be signed.

When a dossier is completed, the fields are added to the file, which is then digitally signed with a certificate. This certificate is trusted by Adobe Reader, as it is part of the Adobe Approved Trust List. The signature allows end users to verify the integrity of the document, proves the document has not been altered, and by whom and when the document has been signed.

Invitees

Invitees are persons asked to sign or review a dossier. Invitees' properties:

  • Name: the name that will be used in communication to address the invitee
  • Fields: locations within a PDF document for information to be added. See fields.
  • Email (optional): the email address that will be used to notify the invitee about this dossier and send the signed document
  • Locale (optional): the locale to be used in invitations and the UI, the default locale is en-US
  • Position (optional): positions determine the order of signing, lower positions will be invited earlier
  • Authentication methods (optional): additional authentication before the user can view the dossier
  • Identification methods (optional): additional identification in order to sign the dossier
  • Notifications (optional): which notifications should be sent, by default all notifications are sent
  • Payments (optional): additional payment before signing the dossier
  • Phone number (optional): the phone number to be used to send an invite or OTP to
  • Reference (optional): allows the invitee it to be linked to an ID known within your organisation
  • Read-only (optional): when read-only the invitee will review instead of sign the dossier
  • Redirect URL (optional): URL to redirect the invitee to after signing, approving or declining the dossier

Fields

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.

Supported field types:

  • signature: the invitee is asked for a signature
  • initials: 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.
  • signatureDate: the date the invitee signed the document, automatically determined
  • text: a text field that can be filled in by the invitee
  • textarea: a multi-line text field that can be filled in by the invitee
  • label: a text field that contains a predefined text which cannot be modified
  • checkbox: a box which can be checked by the user
  • radio: a group of radio buttons, of which one option must be selected
  • stamp: the invitee is asked for its stamp/seal (hanko), mostly used in Asia and Africa

Invites

An invite is a unique URL linked to an invitee to view the dossier. Sign can send these invites to the invitees or you can distribute the URL yourself, for example by redirecting or sending emails yourself. An invite can have a custom expiration time, specified during creation. Creating multiple invites for an invitee is possible.

Supported message channels:

  • email: the invite is send to the email address of the invitee.
  • sms: the invite is send via sms to the phone number of the invitee (only available when configured).
  • whatsapp: the invite is send via WhatsApp Business Platform to the phone number of the invitee (only available when configured).
  • default: the invite URL will be returned in the response for you to distribute yourself.

Owners

A dossier owner is a contact person who will be informed about status updates of the dossier. If set, the owner's name will be used in communication to the invitees, otherwise the organisation name is used instead.

Attachments

Attachments are files attached to the dossier which doesn't have to be signed, for example, a Terms and Conditions document.

Audit report

The audit report contains all info and events related to the dossier for evidence purposes, like documents, owners, invitees, fields and events.

Data retention

Sign is only a signing service and does not store or retain dossiers and documents beyond the expiration date of the dossier, to comply with the General Data Protection Regulation (GDPR). Documents and personal data are anonymized or deleted. It's thus required to download dossiers after completion and to store them within your own company records.

Environments

Sign provides two environments:

  • Sandbox: https://api.sandbox.cmdisp.com/sign/v1/
  • Production: https://api.cmdisp.com/sign/v1/

The sandbox environment is intended 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.

Getting started

The steps for using the service are:

  1. Upload one or more PDF documents that need to be signed
  2. 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.
  3. Create an invite for each invitee to sign/review the document
  4. The end user is directed to the invite URL, for example via email
  5. The end user is presented a web interface where he can read and sign or review and approve the document
  6. The dossier owner is notified of the completion of the dossier
  7. 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 generated
  • nbf: the time after which the token is valid, usually equal to iat
  • 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.

Request

POST https://api.cmdisp.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.cmdisp.com/sign/v1/upload \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjNiNDM4NDM3LTA0YTQtNDBiYi04Mzg5LTU0YmIwMjc2NmZiYSJ9.eyJpYXQiOjE1NDYzMDA4MDAsIm5iZiI6MTU0NjMwMDgwMCwiZXhwIjoxNTQ2MzAwODYwfQ.bwqCUHS1d5d8guAPHDsdd9-a8oXxH1q45O0tDP1asTo' \
  -H 'content-type: multipart/form-data' \
  -F '[email protected]/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.cmdisp.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

Request body

Field placement via web interface

{
    "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.

Request

POST https://api.cmdisp.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 dossier

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.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

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.cmdisp.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.cmdisp.com/sign/v1/dossiers/{dossierId}/download

Events

A webhook can be added to subscribe to events that occur. When an event occurs, a trigger is sent to a predefined URL.

Event webhooks

Supported event types:

dossier.invite.created: an invite has been created.
dossier.invite.expired: an invite has expired.
dossier.invite.undelivered: an invite cannot be delivered.
dossier.invite.viewed: the invite has been viewed by the invitee.
dossier.invitee.state.updated: the invitee state is updated. For example, to approved or declined.
dossier.prepared: the prepare step has been completed: fields are added to the dossier and invites should be sent.
dossier.state.updated: the state of the dossier is updated. For example, from pending to completed.

By default the the dossier.state.updated, dossier.prepared and dossier.invite.undelivered events are sent.

Subscribe to event(s)

Adding a webhook can be done by the using the webhook endpoint. It is mandatory to start the URL with https://.

Request

POST https://api.cmdisp.com/sign/v1/clients/{kid}/webhooks

Replace {kid} with the client Key ID

Request headers

Content-Type: application/json
Authorization: Bearer GENERATED_TOKEN_HERE

Request body

{
    "url": "https://example.com",
    "events": [
        "dossier.state.updated",
        "dossier.prepared",
        "dossier.invite.undelivered"
    ]
}

Custom headers

Custom headers can optionally be provided in the headers field:

{
    "url": "https://example.com",
    "headers": {
        "My-Custom-Header": "Example"
    }
}

Response

{
    "id": "77e79832-1708-4a49-9528-3536ba4057d7",
    "url": "https://example.com",
    "events": [
        "dossier.state.updated",
        "dossier.prepared"
    ],
    "headers": null,
    "updatedAt": "2022-01-01T00:00:00+00:00",
    "createdAt": "2022-01-01T00:00:00+00:00"
}

Retrieve status callback

A webhook URL can be configured for your Key ID so you get notified about status updates for dossiers.

Webhooks can be configured via the API. Check the Swagger documentation for more details.

Request headers

Content-Type: application/json

Request body

{
    "id": "b041a287-bc92-4469-801e-ae1a39c08f6e",
    "type": "dossier.state.updated",
    "dossier": {
        "id": "b659c273-954e-43cf-893a-0f74a7f87153",
        "state": "completed"
    },
    "created": "2022-01-01T00:00:00+00:00"
}

Response

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 several times with an exponentially increasing delay.

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 Swagger API documentation.

Example:

{
    "status": 400,
    "message": "Error message"
}

Use cases

  1. Change language / locale
  2. Send invite using SMS
  3. Send invite using WhatsApp Business Platform
  4. Include invite in your own system
  5. Require identification
  6. Require payment
  7. Cancel a dossier
  8. Configure branding
  9. Configure invitee emails

Swagger API documentation

For a complete technical documentation with specifications for all field types, JSON objects and methods, you can consult our complete swagger specification.

Swagger API documentation