API Based Flow
This flow is best suited for cases where you wish to build (or already have built) your own signing view or user interface. With the API Based Flow you'll take care of handling all the user interactions and use the eID Easy API endpoints only.
At the highest level, an API based signing flow goes as follows:
- File is prepared for signing - this is a single API request
- User signs the file - this might require multiple API requests, polling and/or redirects depending on the signing method. TIP: We also have a couple of front-end components that can handle method specific user interactions and API requests for you. Take a look at our Browser Client and Widget
- Fetch the signed file - fetch and store the signed file, let the user download the signed file
Now, you're already off to a good start on your road to wielding the power of the strongest of the electronic signatures - the mighty QES. Just follow the steps below and get your first file signed with eID Easy 🚀.
NOTE
For this guide, we assume that you wish to get PDF document signed. However, the flows for all other file types are very similar and we provide ample references to file type specific implementation details along the way. If you'd like to know more about specific API calls and all the available options, take a look at our API Reference.
BEFORE YOU CONTINUE
Make sure that you have your eID Easy API credentials at hand as you'll need them in the following steps. You can follow this short guide to obtain the API credentials.
API REFERENCE
In the following guide, we'll use only a small subset of all the available parameters to keep things simple. You can click on the blue endpoint links in this guide to learn more about all the available options. For the full API reference, see: https://documenter.getpostman.com/view/3869493/Szf6WoG1
1. Prepare the file for signing
eID Easy API provides two different endpoints for file preparation.
- https://id.eideasy.com/api/signatures/prepare-add-signature - use this for when you need to add signatures to an already signed .asice container
- https://id.eideasy.com/api/signatures/prepare-files-for-signing - use this for all other cases, including signed PDF files (the first endpoint is only meant for .asice containers)
So, let's prepare a PDF file for signing.
For that we'll send a server-side POST request to https://id.eideasy.com/api/signatures/prepare-files-for-signing
The request body might look something like this:
{
"client_id": "{{client_id}}",
"secret": "{{secret}}",
"container_type": "pdf",
"files": [
{
"fileContent": "JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KL091dGxpbmVzIDIgMCBSDQovUGFnZXMgMyAwIFINCj4+DQplbmRvYmoNCg0KMiAwIG9iag0KPDwNCi9UeXBlIC9PdXRsaW5lcw0KL0NvdW50IDANCj4+DQplbmRvYmoNCg0KMyAwIG9iag0KPDwNCi9UeXBlIC9QYWdlcw0KL0NvdW50IDINCi9LaWRzIFsgNCAwIFIgNiAwIFIgXSANCj4+DQplbmRvYmoNCg0KNCAwIG9iag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDMgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8PA0KL0YxIDkgMCBSIA0KPj4NCi9Qcm9jU2V0IDggMCBSDQo+Pg0KL01lZGlhQm94IFswIDAgNjEyLjAwMDAgNzkyLjAwMDBdDQovQ29udGVudHMgNSAwIFINCj4+DQplbmRvYmoNCg0KNSAwIG9iag0KPDwgL0xlbmd0aCAxMDc0ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBBIFNpbXBsZSBQREYgRmlsZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIFRoaXMgaXMgYSBzbWFsbCBkZW1vbnN0cmF0aW9uIC5wZGYgZmlsZSAtICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjY0LjcwNDAgVGQNCigganVzdCBmb3IgdXNlIGluIHRoZSBWaXJ0dWFsIE1lY2hhbmljcyB0dXRvcmlhbHMuIE1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NTIuNzUyMCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDYyOC44NDgwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjE2Ljg5NjAgVGQNCiggdGV4dC4gQW5kIG1vcmUgdGV4dC4gQm9yaW5nLCB6enp6ei4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjA0Ljk0NDAgVGQNCiggbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDU5Mi45OTIwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNTY5LjA4ODAgVGQNCiggQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA1NTcuMTM2MCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBFdmVuIG1vcmUuIENvbnRpbnVlZCBvbiBwYWdlIDIgLi4uKSBUag0KRVQNCmVuZHN0cmVhbQ0KZW5kb2JqDQoNCjYgMCBvYmoNCjw8DQovVHlwZSAvUGFnZQ0KL1BhcmVudCAzIDAgUg0KL1Jlc291cmNlcyA8PA0KL0ZvbnQgPDwNCi9GMSA5IDAgUiANCj4+DQovUHJvY1NldCA4IDAgUg0KPj4NCi9NZWRpYUJveCBbMCAwIDYxMi4wMDAwIDc5Mi4wMDAwXQ0KL0NvbnRlbnRzIDcgMCBSDQo+Pg0KZW5kb2JqDQoNCjcgMCBvYmoNCjw8IC9MZW5ndGggNjc2ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBTaW1wbGUgUERGIEZpbGUgMiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIC4uLmNvbnRpbnVlZCBmcm9tIHBhZ2UgMS4gWWV0IG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NzYuNjU2MCBUZA0KKCBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY2NC43MDQwIFRkDQooIHRleHQuIE9oLCBob3cgYm9yaW5nIHR5cGluZyB0aGlzIHN0dWZmLiBCdXQgbm90IGFzIGJvcmluZyBhcyB3YXRjaGluZyApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY1Mi43NTIwIFRkDQooIHBhaW50IGRyeS4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NDAuODAwMCBUZA0KKCBCb3JpbmcuICBNb3JlLCBhIGxpdHRsZSBtb3JlIHRleHQuIFRoZSBlbmQsIGFuZCBqdXN0IGFzIHdlbGwuICkgVGoNCkVUDQplbmRzdHJlYW0NCmVuZG9iag0KDQo4IDAgb2JqDQpbL1BERiAvVGV4dF0NCmVuZG9iag0KDQo5IDAgb2JqDQo8PA0KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UeXBlMQ0KL05hbWUgL0YxDQovQmFzZUZvbnQgL0hlbHZldGljYQ0KL0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcNCj4+DQplbmRvYmoNCg0KMTAgMCBvYmoNCjw8DQovQ3JlYXRvciAoUmF2ZSBcKGh0dHA6Ly93d3cubmV2cm9uYS5jb20vcmF2ZVwpKQ0KL1Byb2R1Y2VyIChOZXZyb25hIERlc2lnbnMpDQovQ3JlYXRpb25EYXRlIChEOjIwMDYwMzAxMDcyODI2KQ0KPj4NCmVuZG9iag0KDQp4cmVmDQowIDExDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTkgMDAwMDAgbg0KMDAwMDAwMDA5MyAwMDAwMCBuDQowMDAwMDAwMTQ3IDAwMDAwIG4NCjAwMDAwMDAyMjIgMDAwMDAgbg0KMDAwMDAwMDM5MCAwMDAwMCBuDQowMDAwMDAxNTIyIDAwMDAwIG4NCjAwMDAwMDE2OTAgMDAwMDAgbg0KMDAwMDAwMjQyMyAwMDAwMCBuDQowMDAwMDAyNDU2IDAwMDAwIG4NCjAwMDAwMDI1NzQgMDAwMDAgbg0KDQp0cmFpbGVyDQo8PA0KL1NpemUgMTENCi9Sb290IDEgMCBSDQovSW5mbyAxMCAwIFINCj4+DQoNCnN0YXJ0eHJlZg0KMjcxNA0KJSVFT0YNCg==",
"fileName": "somefiletest.pdf",
"mimeType": "application/pdf"
}
],
"signature_redirect": "http://eid-sample-app.localhost/show-download-signed-file?file_id=AwX4I1Es5T49H2mr",
"return_method_configs": true,
"noemails": true
}
Property | Type | Default | Description |
---|---|---|---|
client_id | string | undefined | Required. Get from id.eideasy.com after signing up. |
secret | string | undefined | Required. Get from id.eideasy.com after signing up. |
container_type | string | undefined | Required. Type of the container in which you wish to receive the signature. Possible values: "asice", "pdf", "cades" or "xades". |
files[].fileContent | string | undefined | Required. A base64 encoded PDF document to be signed. |
files[].fileName | string | undefined | Required. Filename of the document to be signed. |
files[].mimeType | string | undefined | Required. mimeType of the document to be signed. |
signature_redirect | string | undefined | Optional. URL to where the user will be redirected after successful signing. This is only relevant in case you do not use Signature JS for handling the browser-side user interactions. |
return_method_configs | boolean | false | Optional. Whether to return the list of available signing method configs in the response. |
noemails | boolean | true | Optional. Whether to send notification email or not. True will NOT send notification emails. Note that for API clients created before 2024-08-28, the default value is false . |
Note: Don’t forget to set header Content-Type: application/json
Prepare the file for signing response
The API responds with a doc_id
and a list of signing methods that are available for this signing session like this:
{
"status": "OK",
"doc_id": "QLcJD03LUP0S7DUeTGNobQdsiJGfzqRnULrGE0iV",
"method_configs": [
{
"action_type": "mid-signature",
"supported_countries": [
"EE"
]
},
{
"action_type": "smart-id-signature",
"supported_countries": [
"EE",
"LV",
"LT"
]
},
...
]
}
Make a note of the doc_id
value you receive (do not use the one in this example, it is expired) as we'll use it in the next steps.
2. Let user sign the file
IMPORTANT!
For the signature to be valid, you must show the file contents to the use before signing. After signing, you must provide the signed file to the user.
So, you most probably want to have a user interface with a file preview, buttons for selecting different signing methods and elements to handle method specific user interactions. E.g. some signing methods require user input like entering their phone number or personal id code.
If building all that seems like quite a bit of work then you're totally right, it is. That's why we've built a couple of front-end components you can use to handle method specific user interactions and API calls.
Enter the front-end components:
- Browser Client - only handles the method specific API calls. Does not include any UI elements. Useful for when you wish to write your own UI elements.
- Widget - a full-fledged UI component to handle all the signing methods and their user interactions and API calls. Can be used in Vue 2 and React based web apps and works equally well on plain old HTML pages too.
- Signature JS - a small browser-side JavaScript library that you can use to handle eID Easy signing flows in a popup window.
NOTE
If all this seems like more than what you bargained for then you might want to check out this guide which covers our simpler, pre-built Signing Page Flow.
As for the current tutorial, we are going to use the Signature JS to get up and running quickly.
2.1 Setting up the front-end parts
Install the Signature JS:
yarn add @eid-easy/signature-js
npm install @eid-easy/signature-js
We'll then initialize the Signature JS with the following parameters:
const signature = new Signature({
onSuccess: () => {
console.log('User has successfully signed the document');
},
onFail: (error) => {
console.log('Signing failed');
},
});
Property | Type | Default | Description |
---|---|---|---|
onSuccess | function | undefined | Required. This function is called when the user has successfully signed the document. |
onFail | function | undefined | Required. This function is called when the user cancels or fails to sign the document and is unable to continue with the signing process. Note that this function is not called on validation errors or on other errors that the end user can correct and then proceed. |
baseUrl | string | https://id.eaideasy.com | Optional. eID Easy API baseUrl. If you wish to make requests against the sandbox environment, set this to https://test.eideasy.com |
You can now call the signature.start
method in response to a user action. E.g. when they click a "start signing" button in your UI. Note: it is important to call signature.start
inside the user-triggered event handlers, because some browsers (e.g. Firefox) will otherwise block the popup window. See this article for more information.
signature.start({
clientId: /* your client_id */,
docId: /* doc_id you received from the /prepare-files-for-signing API call */,
actionType: 'smart-id-signature',
country: 'EE',
language: 'en', // ISO 639-1 two letter language code,
inputValues: { // optional
email: 'dummy@dummy.it',
username: 'testuser',
phone: '+37212345678',
idcode: '987654321',
},
});
Property | Type | Default | Description |
---|---|---|---|
clientId | string | undefined | Required. Get from id.eideasy.com after signing up. |
docId | string | undefined | Required. doc_id you receive from the /prepare-files-for-signing API call. |
actionType | string | undefined | Required. actionType is the identifier of the signing method you wish to use. You can find the available actionTypes for the current signing session in the response body (the method_configs property) of the prepare files call we made in step 1. |
country | string | undefined | Required. ISO 3166-1 alpha-2 country code. You can find the available countries per each actionType for the current signing session in the response body (the method_configs property) of the prepare files call we made in step 1. |
language | string | undefined | Optional Two letter ISO 639-1 language code. |
inputValues.email | string | undefined | Optional. Signer's email address. This is used to pre-fill the email field in the signing form. |
inputValues.username | string | undefined | Optional. Signer's method specific username. This is used to pre-fill the username field in the signing form. |
inputValues.phone | string | undefined | Optional. Signer's method specific phone number. This is used to pre-fill the phone number field in the signing form. |
inputValues.idcode | string | undefined | Optional. Signers's national id code. This is used to pre-fill the id code field in the signing form. |
And we are almost done! Our end-user can now sign the document we prepared for them. After they have completed the signing process we probably want to fetch the signed file and let the end-user download it.
3. Fetch the signed file
Wait but how do I know when the user has signed the file?
- If you are using our widget, browser client or signature js you can use the
onSuccess
callback function to for example send an AJAX request to your backend. - If you're using the method specific endpoints directly (without the help of our widget or browser client), then you'll be polling the
/complete
endpoint. - Additionally, you can log in to your eID Easy admin dashboard and configure the "Signature notification URL" in the "EDIT" > "Notification hooks" view of your website. eID Easy server will send a POST request (that contains singer_id and doc_id) to this url every time a file gets signed.
NOTE for when you are not using Signature JS to handle the browser-side user interactions
Some signing methods (like the Latvian eParaksts Mobile) are redirect based. This means that end-user gets redirected to the method provider´s website to complete the signing process after which they'll be redirected back to the url you provided for signature_redirect
in the https://id.eideasy.com/api/signatures/prepare-files-for-signing
request. In these cases you can't use the widget's or browser client's onSuccess
callback function. Our recommendation is to use a separate view for displaying the signature success. Provide the url of that view in the /prepare-files-for-signing
request and redirect the user to that same view in the widget's onSuccess
callback. Or in case of SPAs, just render the success view.
Alright, let's get this thing wrapped up. The only thing left to do is to download the signed file. For that, make a POST request to https://id.eideasy.com/api/signatures/download-signed-file:
{
"secret": "{{secret}}",
"client_id": "{{client_id}}",
"doc_id":"{{doc_id}}"
}
doc_id
- the same doc_id you got in step "1. Prepare the file for signing"
Example response:
{
"status":"OK",
"signed_file_contents":"UEsDBBQAAAgAAHI6z06KIflFHwAA",
"signer_id":"34501234215",
"filename":"signed_doc.pdf"
}
signed_file_contents
- signed file in base64 encoding.
signer_id
- signee’s personal ID code.
If the status
is not OK
, then you should not consider the signature to be verified.
And that’s it. Good job! 🙌 You're now able to use the eID Easy API to collect strong electronic signatures in your projects.
Don't forget to check out our showcase of possible integrations with the eID Easy API at https://demo.eideasy.com. You can view the source code here: https://github.com/eideasy/eid-sample-app