Welcome to 'Digital Signing REST API'

Version '2025.10.15.1300'

Getting started

'Digital Signing REST API' is a new cloud platform that provides online 24/7 access to IntraOffice Digital Signature Services. 'Digital Signing REST API' is developed by IntraData and can be used by IntraData's registered partners to implement their digital signing process that may support full automatization, client specific workflows, and integration with client's back office systems. 'Digital Signing REST API' recognizes the OpenApi Specification (OAS). The full overview of the available functionality can can be found on our OAS/Swagger page

Here we will describe the most typical usage scenarios.

Introduction

In order to start a signing process, a signing request should be submitted first that should contain the following details:

When the new request is received, it will get processed. During the process:

'Digital Signing REST API' allows the following:

Envelope

In order to simplify futher explanation will introduce some simple vocabulary.

Each signing request will be referred to as an envelope. Similar to a 'post' envelope, our envelope contains:

Actors

Every party involved in the signing process will be referred to as 'actor'. An actor can be:

Roles

Note that there are situations where actor is not neccessarity the one who signs the document. For example, an actor can be a company's administration department that will only receive the copy of the contract signed by the candidate and the HR when the process finished. Another example, is that some actors are not allowed to delete envelopes. In order to distinguish between different scenarios, roles get introduced. Each role as the name implies, represents a named pre-defined collection of permissions. When submitting a new envelope, each actor should be explicitly assigned to one of available roles. After the envelope is created, it is not possible to change actor's role.

Documents that need to be signed

Each envelope may contain one or several documents that have to be signed. Documents can be sent in a variaty of mime-types (e.g., Word, Excel, Text, Pdf, etc). In some cases, the document should already contain placeholders where the actual signature will be placed. We also support cases, where pre-processing is involved and the placeholders are generated automatically the signing engine. Another examle of pre-processing can be where documents will be merged into one before the signing will start. In order to facilitate
different processing scenarios we introduce document categories. Each document category represents a set of business rules that get executed after envelope is created. When submitting new envelope, each document should be marked to belong to one of the predefined categories.

Documents that do not need to be signed

Envelope can also contain documents that do not need to be signed. These documents will still be sent to the actors. For example, along with the job contract een envelope can also contain a 'welcome new employee' document prepared by company's HR.

Procedures

In some use cases, it might be important that actors get invited to sign according to a specific order. In other uses scenarios it is important that actions get triggered when one of the actors refused to sign. The signing engine is developed to support al those possible workflows. Each workflow represents a set of instructions that will be followed when specific events occur (or not occur) during envelope's lifetime. We will refer to each signing workflow as a 'procedure'. Each procedure is given an unique name and also accepts pre-defined sets of input parameters that should be sent as part of the envelope's payload. When sending the procedure name as part of the envelope we make sure that the right workflow has been used for processing. More on procedures later in the next chapters.

Sending accompanying information

Along with the information required for the signing process, it is also possible to send additional information that is (strictly speaking) not used in the signing process. An example of such information can be an internal employee number that will be assigned to each new employee. This information only makes sense for the business process that has created the envelope. It will be 'attached' to the envelope and can be read back via envelope details. The ability to add 'meta' data to the envelope can be very useful for the client's internal administration. Note that the meta information can be coupled to the envelope itself and/or to each document in the envelope.

Working with procedures

There are procedures that are supported 'out-of-box'. There are also procedures that are custom made for a specific client and specific business process within that client. These custom procedures are indeed only visible/accessible to the client that they were designed for.

List available procedures

To get overview of available procedures, please use the following HttpRequest:


GET /api/v1/procedures

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

[{
	"location": "api/v1/procedures/p1_nl",
	"name": "p1_nl",
	"description": "Digitale handtekening"
	}, 
   {
	"location": "api/v1/procedures/loonheffing_nl",
	"name": "loonheffing_nl",
	"description": "Loonheffing"
	},
   ...
]

Each item in this list contains short information about the procedure:

Read procedure details

The locationattribute from the previous example shows where more information about the procedure can be found.

Example HttpRequest:


GET api/v1/procedures/p1_nl

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
	"name": "p1_nl",
	"description": "Digitale handtekening",
	"roles": [{
			"name": "consultant",
			"description": "Ondertekenaar",
			"minOccurrences": 1,
			"maxOccurrences": 1
		}, {
			"name": "signee",
			"description": "Ondertekenaar",
			"minOccurrences": 1,
			"maxOccurrences": 6
		}
	],
	"categories": [{
			"name": "document",
			"description": "Document",
			"minOccurrences": 0,
			"maxOccurrences": 10,
			"types": ["application/msword", "application/pdf", "application/rtf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
		}
	]
}

As seen in the response, the procedure also has the following attributes:

Each actor role has the following properties:

Each document category has the following properties:

Submitting new envelope

To create a new envelope, the client code should provide instructions and data needed by the signing engine to compete the process (e.g., which procedure should be used, users involoved, etc). And of course, the client code will have to provide documents that need to be singed. There are 3 possibilities to 'upload' document document and make it available for signing: embed document in request body, provide url where singing engine can download document from, and finally upload document to document cache and only sent returned id. More details on the document upload later in the following sesctions.

Bij submitting envelope, the incoming 'package' gets validated and if successfull the processing will begin. Note also that is also possible to 'proof' submit an envelope. In this case, the envelope data will only be validated and no envelope will be submitted when validation has succeeded. More on this in the next chapters.

Submitting envelope with embedded documents

To send document(s) content embedded in request body, the so-called multi mime-type requests should be used. Those requests contain multiple sections. The json section constains instructions and data for the engine. Each other section will correspond to specific document. Here an example of multi mime-type HttpRequest:


POST api/v1/envelopes 
Content-Type: multipart/form-data; boundary="boundary"

--boundary
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data

{ 
   "procedure": "p1_nl",
   "scheduledAt": "2017-10-06T12:10:55+02:00",
   "expiresAt": "2017-10-16T00:00:00+02:00",
   "priority": "normal",
   "description": "this is new job contract for Mr X",
   "documents": [
      {
         "category": "document",
         "description": "This is some job contract",
         "type": "application/msword",
         "fileName": "JobContract.docx",
         "signatures": [
            {
               "field": "Signature1",
               "actor": 0
            },
            {
               "field": "Signature2",
               "actor": 1
            }
         ]
      },
      {
         "category": "document",
         "description": "This is document with information our home policies",
         "type": "application/pdf",
         "fileName": "HomeRules.pdf",
         "properties": {
               "issued by": "HR",
               "issue date": "2019-12-01"
         }
      }
   ],
  "actors": [
    {
      "role": "employee",
      "name": "Mr X",
      "salutation": "Dear Mr X",
      "emailAddress": "mister.x@gmail.com",
      "mobileNumber": "+3134324234"
    },
    {
      "role": "director",
      "username": "director.company",
      "name": "Mr Director",
      "salutation": "Dear Director",
      "emailAddress": "director@company.com",
      "mobileNumber": "+31123213211"
    }
  ],
   "properties": {
      "employee number": "123",
      "employee start date": "2019-12-01"
   }
}}

--boundary
Content-Type: application/msword
Content-Disposition: attachment; filename="JobContract.docx"

{document content}

--boundary

Content-Type: application/pdf
Content-Disposition: attachment; filename="HomeRules.pdf"

{document content}

--boundary--


Example HttpResponse:


HTTP/1.1 201 Created
Location: api/v1/envelopes/2408b745856b41ca8b377c2850d5adfa

As seen in the example HttpRequest, each envelope has the following attributes:

Each document has the following attributes:

Each actor has the following attributes:

Each signature object has the following attributes:

Please note that in order to match document binary content with the document meta data we use Content-Disposition http headers. It is therefore important that the content type and the file name in this header match those in the 'json' part of the request. In case when the envelope validation has been successfull and envelope is created, the 201 (Created) http status code is returned. In case of success, the response message will also have Location http header that points to URL via which the envelope details (including current envelope status) can be read. The last section of this url is 2408b745856b41ca8b377c2850d5adfa which is an unique envelope's id.

Submitting envelope with documents links

Instead of sending document content embedded in http request itself, the client application can provide the URL from which the document content can be downloaded. We assume that the document is accessible via simple GET request. Please be aware that this method is less secure that the first one since it requires that documents are exposed to everone who happen to know their http addresses.

Example HttpRequest:


POST api/v1/envelopes 
Content-Type: application/json; charset=utf-8

{ 
   "procedure": "p1_nl",
   "scheduledAt": "2017-10-06T12:10:55+02:00",
   "expiresAt": "2017-10-16T00:00:00+02:00",
   "priority": "normal",
   "description": "this is new job contract for Mr X",
   "documents": [
      {
         "category": "document",
         "description": "This is some job contract",
         "type": "application/msword",
         "fileName": "JobContract.docx",
         "contentUrl": "https://somefilestorage.com/files/1",
         "signatures": [
            {
               "field": "Signature1",
               "actor": 0
            },
            {
               "field": "Signature2",
               "actor": 1
            }
         ]
      },
      {
         "category": "document",
         "description": "This is document with information our home policies",
         "type": "application/pdf",
         "fileName": "HomeRules.pdf",
         "contentUrl": "https://somefilestorage.com/files/2",
         "properties": {
               "issued by": "HR",
               "issue date": "2019-12-01"
         }
      }
   ],
  "actors": [
    {
      "role": "employee",
      "name": "Mr X",
      "salutation": "Dear Mr X",
      "emailAddress": "mister.x@gmail.com",
      "mobileNumber": "+3134324234"
    },
    {
      "role": "director",
      "name": "Mr Director",
      "salutation": "Dear Director of Some Company",
      "emailAddress": "director@somecompany.nl",
      "mobileNumber": "+31123213211"
    }
  ],
   "properties": {
      "employee number": "123",
      "employee start date": "2019-12-01"
   }
}}


Example HttpResponse:


HTTP/1.1 201 Created
Location: api/v1/envelopes/2408b745856b41ca8b377c2850d5adfa

Submitting envelope with content tokens

Finally, the client code can upload documents self to document cache (aka document content repository). Each document should be uploaded separately and so for each uploaded document an unique cache identifier (aka content token) will be generated. To get url, where document should be uploaded to, the following request can be used:


GET api/v1/documents/commands/createUploadUrl

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json;
{
    "documentUploadUrl": "https://app-io-shared-content-repository.azurewebsites.net/api/public/content?token=xxxxxx"
}

Uploading document to this URL (via POST) will return content token that later can be used when creating envelope as in the example below.

Example HttpRequest:


POST api/v1/envelopes 
Content-Type: application/json; charset=utf-8

{ 
   "procedure": "p1_nl",
   "scheduledAt": "2017-10-06T12:10:55+02:00",
   "expiresAt": "2017-10-16T00:00:00+02:00",
   "priority": "normal",
   "description": "this is new job contract for Mr X",
   "documents": [
      {
         "category": "document",
         "description": "This is some job contract",
         "type": "application/msword",
         "fileName": "JobContract.docx",
         "contentToken": "zzzzzzzzzzzzzzzzzzzzzzzz",
         "signatures": [
            {
               "field": "Signature1",
               "actor": 0
            },
            {
               "field": "Signature2",
               "actor": 1
            }
         ]
      },
      {
         "category": "document",
         "description": "This is document with information our home policies",
         "type": "application/pdf",
         "fileName": "HomeRules.pdf",
         "contentToken": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "properties": {
               "issued by": "HR",
               "issue date": "2019-12-01"
         }
      }
   ],
  "actors": [
    {
      "role": "employee",
      "name": "Mr X",
      "salutation": "Dear Mr X",
      "emailAddress": "mister.x@gmail.com",
      "mobileNumber": "+3134324234"
    },
    {
      "role": "director",
      "name": "Mr Director",
      "salutation": "Dear Director of Some Company",
      "emailAddress": "director@somecompany.nl",
      "mobileNumber": "+31123213211"
    }
  ],
   "properties": {
      "employee number": "123",
      "employee start date": "2019-12-01"
   }
}}


Example HttpResponse:


HTTP/1.1 201 Created
Location: api/v1/envelopes/2408b745856b41ca8b377c2850d5adfa

Validating envelope without submitting

It is possible to validate envelope without actually submitting it. Both create scenarios (embedded documents of document links) can be used. In this case an additonal validateOnly=true url parameter should be added to the endpoint address.

Example HttpRequest with invalid envelope:


POST api/v1/envelopes?validateOnly=true  
Content-Type: application/json; charset=utf-8

{ 
   "scheduledAt": "2017-10-06T12:10:55+02:00",
   "expiresAt": "2017-10-16T00:00:00+02:00",
   "priority": "normal",
   "description": "this is new job contract for Mr X",
   "documents": [
      {
         "category": "document",
         "description": "This is some job contract",
         "type": "application/msword",
         "fileName": "JobContract.docx",
         "contentUrl": "https://somefilestorage.com/files/1",
         "signatures": [
            {
               "field": "Signature1",
               "actor": 0
            },
            {
               "field": "Signature2",
               "actor": 1
            }
         ]
      },
      {
         "category": "document",
         "description": "This is document with information our home policies",
         "type": "application/pdf",
         "fileName": "HomeRules.pdf",
         "contentUrl": "https://somefilestorage.com/files/2",
         "properties": {
               "issued by": "HR",
               "issue date": "2019-12-01"
         }
      }
   ],
  "actors": [
    {
      "role": "employee",
      "name": "Mr X",
      "salutation": "Dear Mr X",
      "emailAddress": "mister.x@gmail.com",
      "mobileNumber": "+3134324234"
    },
    {
      "role": "director",
      "name": "Mr Director",
      "salutation": "Dear Director of Some Company",
      "emailAddress": "director@somecompany.nl",
      "mobileNumber": "+31123213211"
    }
  ],
   "properties": {
      "employee number": "123",
      "employee start date": "2019-12-01"
   }
}}


Example HttpResponse:



HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

[{
		"PropertyName": "Procedure",
		"Data": {
			"ErrorType": "IntraOffice.Nuget.Exceptions.Types.ModelValidations.PropertyValueNotSetException",
			"ErrorId": "636927397019603343",
			"Message": "Property value not set",
			"ModelType": "CreateEnvelopeVm",
			"PropertyName": "Procedure",
			"AdditionalData": "{}"
		},
		"ModelType": "CreateEnvelopeVm",
		"ErrorType": "PropertyValueNotSetException",
		"Message": "Property value not set"
	}, {
		"PropertyName": "ExpiresAt",
		"Data": {
			"ErrorType": "IntraOffice.Nuget.Exceptions.Types.ModelValidations.PropertyValueNotSetException",
			"ErrorId": "636927397019643332",
			"Message": "Property value not set",
			"ModelType": "CreateEnvelopeVm",
			"PropertyName": "ExpiresAt",
			"AdditionalData": "{}"
		},
		"ModelType": "CreateEnvelopeVm",
		"ErrorType": "PropertyValueNotSetException",
		"Message": "Property value not set"
	}
]

When validating an invalid envelope a collection of validation errors is returned. When a valid envelope is validated, empty collection is returned.

Working with envelopes

In this chapter we will show typical operations to work with already created envelopes.

Reading envelope details

Given envelope's id returned during the submission, one can read back envelope's data used to create envelope. The response will also return informtion about current progress of the envelope.

Example HttpRequest:


GET api/v1/envelopes/{envelope id} 

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
	"id": "{envelope id}",
	"domain": "My Company B.V.",
	"description": "this is new job contract for Mr X",
	"dateSubmitted": "2019-05-06T09:54:21+00:00",
	"task": "employee",
	"currentTask": {
		"role": "employee",
		"description": "Signing by employee",
		"dateScheduled": "2019-05-06T09:54:21+00:00",
		"expirationDate": "2019-05-06T10:54:21+00:00"
	},
	"properties": {...},
	"documents": [...],
	"actors": [...	]
}

As seen in the response, the envelope has no 'dateFinished' attribute set which implies that the signing process is still running. For 'active' envelopes, currentTaskattribute points to the current activity which is now processing the envelope. In the example above, the envelope is waiting to be signed by the employee. When the signing process has completed, the HttpResponse will contain 2 additional attributes:

Here is an example of succefully processed envelope:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
   ...
	"dateSubmitted": "2018-07-06T09:44:59+00:00",
	"dateFinished": "2018-07-06T09:48:05+00:00",
	"result": true,
   ...	
}

Reading envelope events

During the lifetime of an envelope, it will pass through several states. Each state change will be registered as an event. Those events will be saved by the system and can be later used for audit purposes. An example of en event can be, creation of envelope, sending invitation message to an actor, deploying signed document to storage etc. Given envelope's id, it is possible to read all his events that happened to him so far via the following HttpRequest:


GET api/v1/envelopes/{envelope id}/events

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

[{
		"description": "Envelope created for procedure 'xxx'",
		"eventName": "envelopeCreated",
		"timestamp": "2018-05-17T13:27:54.6828921+00:00"
	}, {
		"description": "Procedure started on 17-5-2018 15:28:03 to finish before 24-5-2018 15:27:35",
		"eventName": "envelopeSubmitted",
		"timestamp": "2018-05-17T13:28:03.1207032+00:00"
	}, {
		"description": "Task 'Signing by employee' scheduled at 17-5-2018 15:28:04 to finish before 23-5-2018 15:28:04",
		"eventName": "taskScheduled",
		"timestamp": "2018-05-17T13:28:04.3707252+00:00"
	}, {
		"description": "Message 'Please sign documents' is sent to 'xxx@xxx.nl'",
		"eventName": "messageSent",
		"timestamp": "2018-05-17T13:29:09.1857384+00:00"
	}, {
		"actorName": "Actor XXX",
		"description": "Task 'Signing by actor' is finished",
		"eventName": "actorTaskSucceeded",
		"result": true,
		"timestamp": "2018-05-18T10:12:59.2799394+00:00"
	}, 

	...

	{
		"description": "Procedure is finished",
		"eventName": "envelopeFinishedSucceeded",
		"timestamp": "2018-07-05T13:44:14.3881336+00:00"
	}
]

Reading envelope messages

Again for audit purposes, all messages that have ever been sent to actors also get saved for every envelope. To get those messages, please use the following HttpRequest:


GET api/v1/envelopes/{envelope id}/messages

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

[{
		"dateScheduled": "2018-05-18T07:55:27+00:00",
		"dateSent": "2018-05-18T07:56:05+00:00",
		"mailAddress": "xx@xxx.nl",
		"actorName": "Actor 1",
		"description": "Inviting signee",
		"subject": "There are documents wating to be signed by you"
	}, 
   ...
]

Reading envelope documents

In one of the previous example we have shown how to read back envelope's details. Please be aware that in this case only document metadata will be returned. This is done for performance reasons to avoid sending unnessary data over the wire when only meta details are neccessary. In order to read back binary content of the envelope's document a separate HttpRequest is needed. It is possible to download only one document at a time. To indicate which document we need, document index in the document collection can be used.

En example HttpRequest:


GET api/v1/envelopes/{envelope id}/documents/{document index}/content 

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="JobContract.pdf"

{document content} 

Note that the document content is returned as aplication/pdf type. This is because envelope's documents will be converted to pdf after submission so that their content can no longer be altered and so all the actors will deal with very same version of those documents.

There is also another way to get document content using document id. Similar to envelope id it gets generated during envelope's submission. Each document will receive its own unique identifier. The document id is actually returned when reading back envelope's details as shown in this example HttpResponse:


{
...
	"documents": [{
			"guid": "19fd53492d744ca3b795208dfd19f8aa",
			"description": "This is some job contract",
			"type": "application/msword",
			"category": "document"
		}, {
			"guid": "4a9b3f8693bf4ab68570f082b35ca03b",
			"description": "This is document with information our home policies",
			"type": "application/pdf",
			"category": "document"
		}
	]
...
}

Here guid is unique's document identifier. Given document id, one can download document content via the following request:


GET api/v1/envelopes/{envelope id}/documents/{document id}/content

Example HttpResponse:


HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="JobContract.pdf"

{document content} 

Deleting envelope

In some cases, it is neccessary to be able to stop the signing process in case no agreement can be achieved between involved actors. We will refer to this process as revokingan envelope. The following HttpRequest will show how to 'revoke' an envelope:


POST api/v1/envelopes/active/{envelope id}/method/revoke 

Example HttpResponse:


HTTP/1.1 204 No Content

After being revoke, the envelope can no longer be read back. It is also not possible to 're-start' the signign process. If it is still decided to continue, a new envelope should be submitted. Note that after revoking, all the actors involved in the signing process will be notified that the signing has been aborted. It is also possible to delete envelopes that have already been completed and it is no longer necessary to keep them online. The client may decide to 'move' already signed envelopes to own storage. In order to delete envelope, please use the following HttpRequest:


DELETE api/v1/envelopes/{envelope id}

Example HttpResponse:


HTTP/1.1 204 No Content

Additional information

In this chapter we will cover some other important aspects the client applicatin should be aware of to be able to work with 'Digital Signing REST API';

Security

'Digital Signing REST API' uses authentication/authorization mechanism based on Json Web Tokens tokens (JWT). Each token contains information about the caller and is cryptographically signed. More information about the JWT specificiation can be found on the following site https:\\jwt.io. We expect that each incoming HttpRequest contains Authorization http header of the following format:


Authorization: Bearer {jwt token}

The tokens are issued by IntraData and contain information about the caller. To get more information about token generation, please contact our support desk.

Localization

'Digital Signing REST API' also supports localization. It is possible to specify explicity the preferred language of the communication via supplying Accept-Language http header.

Example HttpRequest:


Accept-Language: nl-NL

When no Accept-Language header found, the default server culture will be used for generated notifications.