# How to create a document
Learn how to obtain signatures on one or several documents with our signature API.
First some basics. Make sure that you have done the following:
- Create an account (opens new window).
- Read our quick start guide
- Learn how to create and use API tokens
Then, follow the steps under Basic request and modify according to your needs as described in the sections below. There are several different steps you can add to a basic request.
# On documents
The following document-related options are available:
- Add multiple documents
- Adjust the deadline
- Add document tags
- Add department ID
# On signers
The following signer-related options are available:
- Signature control
- SMS / email notifications
- Redirect
- Authenticate before signing
- Get social security number
- Set up signature methods
# Basic request
# Step 1 - Create document
This simple request is all you need to get a document signed.
POST https://api.signicat.io/signature/documents
Request sample
{
"title": "Test document",
"signers": [
{
"externalSignerId": "uoiahsd321982983jhrmnec2wsadm32",
"redirectSettings": {
"redirectMode": "donot_redirect"
},
"signatureType": {
"mechanism": "pkisignature"
},
}
],
"dataToSign": {
"title": "Document title",
"description":"Document description",
"base64Content": "VGhpcyB0ZXh0IGNhbiBzYWZlbHkgYmUgc2lnbmVk",
"fileName": "sample.txt",
},
"contactDetails": {
"email": "test@test.com",
"url": "https://signicat.com"
},
"externalId": "ae7b9ca7-3839-4e0d-a070-9f14bffbbf55",
"description": "This is an important document"
}
# Step 2 - Read response
The response you retrieve will look similar to this
{
"documentId": "94865b6f-2aa9-436d-8b3c-a85e00efd034",
"signers": [
{
"id": "f8c6230c-887f-40bf-9438-ab7d005fea5f",
"links": [],
"externalSignerId": "uoiahsd321982983jhrmnec2wsadm32",
"redirectSettings": {
"redirectMode": "donot_redirect"
},
"signatureType": {
"mechanism": "pkisignature"
}
}
],
"status": {
"documentStatus": "unsigned",
"completedPackages": [],
"attachmentPackages": {}
},
"links": [],
"title": "Test document",
"description": "This is an important document",
"externalId": "ae7b9ca7-3839-4e0d-a070-9f14bffbbf55",
"dataToSign": {
"title": "Document title",
"description": "Document description",
"fileName": "sample.txt"
},
"contactDetails": {
"email": "test@test.com",
"url": "https://signicat.com"
}
}
As you can see, a URL is included in the signer object. This is where the signer needs to be redirected.
# Step 3 - Retrieve signed file
When the document is signed and ready, it's time to retrieve the signed file.
# Add multiple documents
# Attachment types
When you upload an attachment, you must decide which attachment type you want to use. The default value is "show_accept"
You can choose between 3 types of attachments:
Type | Description | Remarks |
---|---|---|
show_accept | The signer will see the attachment and have to click a continue button before they get to the main document. | Default |
read_accept | The signer has to click on a checkbox to confirm that they have read and understood the contents of the attachment. | |
sign | The signer has to sign the attachment with the same signature method as the main document. | Extra cost per signature |
# Implementation guide
# Step 1: Create document
First, you have to create the document:
POST https://api.signicat.io/signature/documents
Request sample:
{
"title": "Test document",
"description": "This is an important document",
"externalId": "ae7b9ca7-3839-4e0d-a070-9f14bffbbf55",
"dataToSign": {
"base64Content": "VGhpcyB0ZXh0IGNhbiBzYWZlbHkgYmUgc2lnbmVk",
"fileName": "sample.txt",
},
"contactDetails": {
"email": "test@test.com",
"url": "https://idfy.io"
},
"advanced": {
"attachments": 2
},
"signers": [
{
"externalSignerId": "uoiahsd321982983jhrmnec2wsadm32",
"redirectSettings": {
"redirectMode": "donot_redirect"
},
"signatureType": {
"mechanism": "pkisignature"
},
}
],
}
This is an example of what the request can look like. Notice how we have added the advanced object with "atttachments": 2. This way we are stating that we will upload two more documents in addition to the main document. When you include attachments here, the document job will wait until all the attachments are uploaded before anyone is allowed to sign or notifications are sent.
Things to consider:
# Step 2: Upload attachments/additional documents
Include the document ID you retrieved in step 1 as a path parameter.
POST https://api.signicat.io/signature/documents/{documentId}/attachments
Request sample:
{
"fileName": "Attachment1.pdf",
"title": "Attachment 1 - Type description",
"data": "Base 64 encoded pdf",
"description": "This attachment describes bla bla bla...",
"type": "show_accept",
"signers": null
}
Requirements:
- The fileName property must include a valid extension (e.g. PDF).
- The data property must be a valid base64 encoded string which is a valid document in the correct format.
How to restrict attachment retrieval
If you only want some of the signers to retrieve an attachment, specify which in the signers property, which is set to null in the example above. The data type is a list with the signer IDs you want to include.
# Step 3: Result
When all the attachments are uploaded, the document job will continue its work and the document can be signed.
# Step 4: Read response you retrieved in step 2
The response you retrieve will look something like this:
{
"documentId": "9bdb48c9-1123-49d5-a91b-a8eb0099bc48",
"signers": [
{
"id": "6070e7ff-db6b-4141-9324-a8eb0099bc6b",
"url": "https://sign-test.idfy.io/start?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJrdmVyc2lvbiI6IjdmNzhjNzNkMmQ1MjQzZWRiYjdiNDI0MmI2MDE1MWU4IiwiZG9jaWQiOiI5YmRiNDhjOS0xMTIzLTQ5ZDUtYTkxYi1hOGViMDA5OWJjNDgiLCJhaWQiOiJkNjJhODZjZi04N2FkLTQwYTgtOTExMy1hMjg5MDA3MTk2ODYiLCJsZyI6bnVsbCwiZXJyIjpudWxsLCJpZnIiOmZhbHNlLCJ3Ym1zZyI6ZmFsc2UsInNmaWQiOiI2MDcwZTdmZi1kYjZiLTQxNDEtOTMyNC1hOGViMDA5OWJjNmIiLCJ1cmxleHAiOm51bGwsImF0aCI6bnVsbCwiZHQiOiJUZXN0IGRvY3VtZW50IiwidmYiOmZhbHNlLCJhbiI6IkJhbmtJRCBtb2JpbCB0ZXN0IiwidGgiOiIiLCJzcCI6bnVsbCwiZG9tIjpudWxsLCJyZGlyIjpmYWxzZSwidXQiOiJ3ZWIiLCJ1dHYiOm51bGwsInNtIjoidGVzdEB0ZXN0LmNvbSJ9.DPBcJkasry7UN-ad7yw6vwv5lsWnfybJ9q6LwX4L5fIksL1Kv-WRhV4bYKE793l6",
"links": [],
"externalSignerId": "uoiahsd321982983jhrmnec2wsadm32",
"redirectSettings": {
"redirectMode": "donot_redirect"
},
"signatureType": {
"mechanism": "pkisignature",
"onEacceptUseHandWrittenSignature": false
},
"tags": [],
"order": 0,
"required": false
}
],
"status": {
"documentStatus": "waiting_for_attachments",
"completedPackages": [],
"attachmentPackages": {}
},
"title": "Test document",
"description": "This is an important document",
"externalId": "ae7b9ca7-3839-4e0d-a070-9f14bffbbf55",
"dataToSign": {
"fileName": "sample.txt",
"convertToPDF": false
},
"contactDetails": {
"email": "test@test.com",
"url": "https://idfy.io"
},
"advanced": {
"attachments": 2,
"requiredSignatures": 0,
"getSocialSecurityNumber": false
}
}
As you can see, a URL is included in the signer object. This is where the signer has to be redirected.
# Step 5: Retrieve signed file
When the document is signed and ready, it is time to retrieve the signed document.
# Optional: include email / SMS notifications
We can handle email / SMS notifications regarding this document. Read more about this on the API documentation.
# Adjust a deadline
Deadlines for signing a document can be set on the document itself or on a specific signer. Deadlines can be updated after a document has been created.
# Properties
Property | Description | Default | Max |
---|---|---|---|
deadline | When the document expires | 45 days | 45 days |
deleteAfterHours | How long should we keep the document/data after it is signed or expired | 168 hours | 744 hours |
# Set document deadline
You can adjust how long the deadline to sign a document should be. Note: We keep some metadata about the document beyond this time.
POST https://api/idfy.io/signature/documents
Request sample
{
...
"advanced": {
"timeToLive": {
"deadline": "2018-02-20T07:58:05Z",
"deleteAfterHours": 5
}
}
...
}
Incomplete request
This is not a complete create document request, just an example of how to set the document deadline.
# Set signer deadline
It is also possible to set an individual deadline for each document signer.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
...
"signUrlExpires": "2018-02-18T07:58:05Z"
...
}]
...
}
Incomplete request
This is not a complete create document request, just an example of how to set the document deadline.
# Change document deadline
If you need to change the document deadline you can do it by doing a document update.
# Set required signatures
Our API allows you to set the number of required signatures. For example, if you want to send the document link to 10 signers, but it is enough if 5 of them sign the document, set up the 10 signers as usual and set requiredSignatures to 5. The default value of requiredSignatures will equal the number of signers on the document.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"advanced": {
"requiredSignatures": 5
}
...
}
# Set up signer queue
You can set up a signer queue if you want. This way you can easily manage the signature flow. This can be done in two ways:
# Required signers
If you mark a signer as required, this signer will have to sign the document before anyone else is allowed to sign.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
...
"required": true,
...
}],
...
}
# Signer order
You can configure the order in which signers sign an order. Here is an example with 5 signers.
Signer | Order | Explained |
---|---|---|
Signer 1 | 1 | Can sign instantly |
Signer 2 | 1 | Can sign instantly |
Signer 3 | 2 | Can sign when signers 1 and 2 have signed |
Signer 4 | 3 | Can sign when signer 3 has signed |
Signer 5 | 3 | Can sign when signer 3 has signed |
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
...
"order": 1,
...
}, {
...
"order": 2,
...
}, {
...
"order": 3,
...
}, {
...
"order": 3,
...
}, {
...
"order": 1,
...
}],
...
}
# SMS / Email notifications
In our signature API you can specify if you want us to notify the signers via email or SMS on your behalf. Our notification service lets you manage most of the content in the notification, if you want to, of course. We also supply standard texts if you want the quick and easy solution.
# Structure
The create document request has a notification object where you can specify core settings which will be shared between the signers. This is where you set up arrays of texts for given languages if you want to create your own. In addition to this core object, you have to specify what kind of notifications each signer should get.
# Email / SMS texts
The default texts can be overridden. How you override them is up to you.
- Specify texts in the API request: see step 2 below for details.
- Override the default texts for your account: you can override texts from the Text API tool in the Dashboard. Refer to the Custom texts page for further information.
# Step 1: Implementation
Decide when you want each signer to be notified by including a notifications object for each signer (this object can be null on the signers you don't want to notify)
POST https://api.signicat.io/signature/documents
Request sample
{
....
"signers": [ {
...
"notifications": {
"setup": {
"request": "sendBoth",
"reminder": "sendEmail",
"signatureReceipt": "sendSms",
"finalReceipt": "off"
},
"signerInfo": {
"mobile": {
"countryCode": "+47",
"number": "99999999"
},
"email": "test@test.com"
}
...
}]
....
}
Mobile numbers
Mobile must contain a valid phone number and country code. The country code must either start with + (i.e. +47) or no prefix (i.e. 47).
# Step 2: Shared settings
Note
This step is optional for all notification types except reminders.
Set up shared notification settings if you want to create your own texts, include documents as an attachment in the email (beware of the security issues when sending sensitive documents by email), or if you are using reminders you also have to specify a cron expression for the reminder interval.
You can create texts in different languages, these will then be matched to the languages you have set on the signers (under UI object). If no language is specified, it will default to the English text.
POST https://api.signicat.io/signature/documents
Request sample
{
....
"notification": {
"signRequest": {
"includeOriginalFile": true,
"email": [{
"language": "en",
"subject": "Signing of house contract",
"text": "Please sign this contract .....",
"senderName": "Test"
}],
"sms": [...]
}
}
....
}
You are now ready to go! Keep on reading to learn about more advanced features.
# Step 3: Advanced settings (optional)
Features for advanced users
# Notification merge fields
If you create your own notification texts, you can include some "merge-fields" in your text. When the notification is due, we will replace the mergefield with the appropriate data. We currently support the following fields:
Key | Value |
---|---|
{document-title} | We insert the title of the main document if it exists, if not, the document job title is used. |
{document-description} | We insert the description of the main document, if not, the document job description is used |
{signable-document-titles} | A comma separated list of all the signable documents/files |
{readonly-document-titles} | A comma separated list of all the read-only documents/files |
{deadline} | We insert the deadline to sign the document |
{signed-time} | (For use in signatureReceipt, format: HH:mm:ss) |
{signed-date} | (For use in signatureReceipt, format: yyyy-MM-dd) |
{signed-name} | (For use in signatureReceipt, we insert the name retrieved from the signature method provider) |
{signature-method} | (For use in signatureReceipt, specifies which signature method was used ) |
{url} | We insert the sign URL here. It will only work on request and reminder sms notifications (in email notifications the sign URL is always included as a button themed with the same colour as the sign application) |
# Usage examples
- The document with title {document-title} is now ready to be signed....
- You must sign the document titled {document-title} before {deadline}...
# Signer specific merge fields
If you set up your own email texts for the document, you may want part of the text to be specific to each signer. To solve this, we have introduced signer-specific merge fields. They work the same way as the regular merge fields above, but you can control both the key and value. Just include a dictionary of mergeFields per signer, we will then search for these keys in your text, and insert the value if it exists.
POST https://api.signicat.io/signature/documents
Request sample
{
....
"signers": [ {
...
"notifications": {
"mergefields": {
"{sign-before}": "15 March"
"{conditional-arrival}": "14 April"
}
}
...
}]
....
}
# Usage example
Include your own custom texts as above, for example: "..If you sign this document before {sign-before}, you will retrieve the product at {conditional-arrival}...."
Will be shown as "..If you sign this document before 15 March, you will retrieve the product at 14 April...."
# Reminder schedule
If you set up reminders, you need to specify a schedule in cron format (quartz). There are multiple resources on the web to help you set up the schedule. Here are some of them:
- https://www.freeformatter.com/cron-expression-generator-quartz.html
- http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
# Force authentication before signing
If the documents contain sensitive information, you should include authentication before signing. Authentication before signing requires the user to authenticate themselves before they can open the document to be signed.
# Mechanisms
Mechanism | Explained |
---|---|
off | No auth before sign mechanism, anyone with the sign URL can see the document. |
eid | Before the user can see the document, they have to authenticate with eID. |
smsOtp | Before the user can see the document, they have to authenticate with SMS OTP. |
eidAndSmsOtp | Before the user can see the document, they have to authenticate with eID or SMS OTP. |
# Authentication before signing with eID
To use eID authentication before signing, you either need the signer's national identification number, or their ID provider's unique ID (i.e. the Norwegian BankID personal ID).
POST https://api.signicat.io/signature/documents
Request sample
{
....
"signers": [ {
...
"authentication": {
"mechanism": "eid",
"socialSecurityNumber": "12345678987"
}
...
}]
....
}
# Authentication before signing with SMS OTP
To use SMS OTP authentication before signing, you have to define the signer's mobile phone numbers.
POST https://api.signicat.io/signature/documents
Request sample
{
....
"signers": [ {
...
"authentication": {
"mechanism": "smsOtp",
},
"signerInfo": {
"mobile": {
"countryCode": "+47",
"number": "99999999"
}
}
...
}]
....
}
# Set up signature methods
A short guide to defining signature methods for a signer. The signature method setup is done on each signer.
POST https://api.signicat.io/signature/documents
Request sample
{
....
"signers": [{
...
"signatureType": {
"mechanism": string,
"signatureMethods": []
}
...
}]
....
}
# Step 1: choose mechanism
First you should choose a signature mechanism.
Valid values: pkisignature
, identification
, handwritten
, handwritten_with_identification
.
PKI signature This is the strongest signature mechanism we offer. The document (specifically a hash of the document) is signed following the Public Key Infrastructure.
A simplified explanation:
- The signer signs the document (hash) using their private key.
- The document issuer and/or the signer receives the signed document along with the public key.
- If the public key is unable to decrypt the signature, it means that the signature does not belong to the signer or it has been tampered with.
- If the decrypted signature matches the hash of the original document, it is valid.
Identification A more lightweight solution is to use the identification mechanism.
When using identification, you don't sign the document in the same way as with PKI signature. The signer must agree that they have read and understood the documents and are ready to sign them, then they do a login / identification to confirm their identity.
A simplified explanation:
- The signer accepts the documents and does a login/identification.
- A trace of the signer actions, document hash, and the identification mechanism ID is added to an XML file.
- This XML is sealed inside a PAdES (https://en.wikipedia.org/wiki/PAdES).
- The signature is valid as long as the PAdES is valid.
Only PDF files are supported for identification (because we need the PAdES as proof).
Handwritten Follows the same flow as Identification, just replace the login / identification with a handwritten signature.
Handwritten with identification The PAdES includes both the handwritten signature and the proof of identification.
# Step 2: Specify signature methods
You may specify a list of signature methods, by default all methods set up on your account are included.
Method | Value | Identification | PKI signature |
---|---|---|---|
Norwegian BankID | no_bankid_oidc | Yes | No |
Norwegian BankID on Mobile | no_bankid_mobile | Yes | Yes |
Norwegian Netcentric BankID | no_bankid_netcentric | Yes | Yes |
Norwegian Buypass | no_buypass | Yes | Yes |
Danish NemID | da_nemid | Yes | Yes |
FTN | fi_eid | Yes | No |
Swedish BankID | se_bankid | Yes | Yes |
SMS one time password* | sms_otp | Yes | No |
*The mobile number acts as identification ID, along with a user-entered name/date of birth.
# Add tags to a document
There are several benefits to adding tags to a document:
- You can query your documents with tags at a later time.
- The tag is included in webhooks and events, this way it is easy to separate document events based on tags.
- You can add a tag filter to a webhook to make sure it only forwards events for documents with the specified tag.
# Example
POST https://api.signicat.io/signature/documents
Request sample
...
"advanced": {
"tags": [
"departement_2",
"sales"
]
...
# Add department ID to a document
If you want to mark the documents on your invoice with separate departments you have to specify it in the departementId field
POST https://api.signicat.io/signature/documents
Request sample
{
...
"advanced": {
"departmentId": "A-1702"
}
...
}
# Get social security number
If your BankID certificate allows it, you can retrieve the signer's national ID number.
# For all signers on the document
Set the following property to true if you want to retrieve the national ID number for all signers on the document.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"advanced": {
"getSocialSecurityNumber": true
}
...
}
Requirements
Your BankID certificate must have the rights to retrieve national ID numbers for this feature to work. This is always enabled in our test environment, but might not be activated if you use your own certificate for production. Contact us at support@signicat.io when in doubt.
# For a single signer
Set the following property to true to retrieve for this signer only. The global variable advanced.getSocialSecurityNumber will ovveride this when set to true.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
"getSocialSecurityNumber": true
}]
...
}
Requirements
Your BankID certificate must have the rights to retrieve national ID numbers for this feature to work. This is always enabled in our test environment, but might not be activated if you use your own certificate for production. Contact us at support@signicat.io when in doubt.
# Redirects
It's up to you how you want to implement signing in your application flow. For each signer, you need to specify how you want the user to be redirected when the signing process is complete.
# Request example
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
...
"redirectSettings": {
"redirectMode": "donot_redirect"
}
...
]
...
},
Redirect modes:
Redirect mode | Explained | Depends on |
---|---|---|
donot_redirect | The user will not leave our page during the signature process. | Nothing |
redirect | The user will be redirected to the specified URLs on error/abort/success. | error, cancel, success |
iframe_with_webmessaging | You iframe our application and can use webmessaging to do what you want on success/error/abort. No redirect is executed. | domain |
iframe_with_redirect | You iframe the application, with no use of webmessaging. The signer will be redirected to the specified URLs | error, cancel, success |
iframe_with_redirect_and_webmessaging | You get both redirect and webmessaging. | error, cancel, success, domain |
# Step 1: Create request with redirects
Be sure to include error, cancel and success URLs in the redirectSettings object. The format should be a valid url with no special characters. If you have special characters, be sure to URL encode them.
POST https://api.signicat.io/signature/documents
Request sample
{
...
"signers": [{
...
"redirectSettings": {
"redirectMode": "redirect",
"success": "https://example.com/sign/success",
"cancel": "https://example.com/sign/cancel",
"error": "https://example.com/sign/error"
}
...
]
...
},
# Step 2: Sign or cancel
Let the signer do what they want to do.
# Step 3: Retrieve the redirect response
To make it easy for you to read some core data about the signature status, we append a jwt token to the URLs you defined. It will look like this:
https://example.com/sign/success?idfy-jwt=<jwt is inserted as a query parameter called idfy-jwt>
If you use this token, you have to parse and validate it as described in step 4.
# Step 4: Parse and validate the JWT (optional)
Use our JWT API to parse and validate the JWT included in the redirect URL.
POST https://api.signicat.io/jwt/validate
Request sample
{
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJBY2NvdW50SW......"
}
Note
This endpoint requires a valid API token.
The response will look something like this:
{
"valid": true,
"payload": {
"AccountId": "9740db0f-9b3d-4b54-a6d2-a8ff00ca3f8f",
"DocumentId": "1c7ba8ad-e31d-4960-a734-a9d100645ea7",
"ExternalId": "6e10007b-0fcd-4366-8941-dc685b2a6c13",
"SignerId": "9f075a47-e9af-4055-abe2-a9d10064630b",
"ExternalSignerId": "aaef0308-62a7-4d53-9c37-4627fce44841",
"Error": null,
"SignSuccess": {
"SignatureMethodUniqueId": "9578-6000-4-54133",
"FirstName": "MIKKEL OLUF",
"MiddleName": null,
"LastName": "RIESTO",
"FullName": "RIESTO, MIKKEL OLUF",
"DateOfBirth": "1910-01-01",
"SignatureMethod": 0,
"SignedTime": "2019-01-10T06:07:21"
},
"Expires": "2019-01-10T06:17:50.8738609Z",
"Aborted": null,
"kid": "f816670a42834756b9f54f4893a1811f"
}
}
Note
You should verify that the valid property is true and that the JWT is not expired (payload.expires).
# Converting files
Our API supports conversion of the most common filetypes (docx, odt, txt, ..) to the pdf format within the API call if you don't want to do that yourself.
You just have to set the convertToPDF
property to true:
POST https://api.signicat.io/signature/documents
Request sample:
{
...
"dataToSign": {
"convertToPDF": true
}
...
}