# 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:

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.

Note

We now support our existing Express Electronic Signing solutions on our new Digital Trust Platform (DTP).

If you are a new customer or have recently migrated to our new platform, see our guide on setting up an API integration (opens new window) instead of following the steps above.

You or your onboarding manager will also need to to enable the ID Methods you want to use in our Dashboard at https://dashboard.signicat.com/bca/authn (opens new window).

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

Note

If you are a new customer or have recently migrated to our new platform, notification settings are now self-serviceable through our Dashboard. See our Communication service documentation (opens new window) for information on managing configurations for SMS messages and email.

# 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 /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 /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 /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:

# 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 /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 /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 /documents

Request sample

{
  ....
  "signers": [{
    ...
    "signatureType": {
      "mechanism": string,
      "signatureMethods": []
    }	
    ...
  }]

  ....
}

Note

If you are a new customer or have recently migrated to our new platform, you or your onboarding manager will also need to to enable the ID Methods you want to use in our Dashboard at https://dashboard.signicat.com/bca/authn (opens new window).

# 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 /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 /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 /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.com 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 /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.com 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 /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 /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

If you are a new customer or have recently migrated to our new Digital Trust Platform (DTP), you will need to use the URL https://api.signicat.com/express/sign/jwt/validate in your POST request instead.

Note that 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 /documents

Request sample:

{
  ...
  "dataToSign": {
    "convertToPDF": true
  }
  ...
}
Last updated: 01/03/2024 08:08 UTC