Sign API v2 integration guide
Set up an API integration
Setting up an API integration is the most flexible way of testing our signature solutions. You can use your preferred IDE, framework, Postman, etc. using credentials provided by Signicat.
Before you set up an API integration, we recommended that you familiarise yourself with the most common integration use cases and the OpenAPI reference documentation to learn about available endpoints and their properties.
If you are looking for an automated business-to-business (B2B) signing and sealing process that does not require end-user interaction, see our Merchant signing feature guide.
Using the API
The most basic signature process will consist of the following steps:
- Prerequisites.
- Upload a document.
- Create a document collection.
- Create a signing session.
- Redirect the end-user to the signature application.
- Get the result from the signing session.
- Download the signed document.
The code snippets below are kept brief for clarity and are provided as examples, not production code. For example, error handling is omitted.
1. Prerequisites
Before you can start making requests to this API, you need to learn how to connect to it. To do this, follow steps 1-3 in the Connect to Signicat APIs Quick start guide.
Ensure that you set permission Signature API for your API client.
2. Upload a document
Once you have obtained an access token, you're ready to upload your first document to be signed. We support both PDFs and plain text documents, and the operation is as simple as making an HTTP POST request with the document's binary data to the Documents endpoint of the API. There is no Base64 conversion or similar. You simply read the document as binary data and send it directly to the server.
We do not currently support signing of already signed PDFs or text files for authentication-based signing. If an end-user tries to sign an already signed document, the signing process may fail.
We do support signing already signed PDF files with PKI signing (for example, Norwegian BankID PKI signing).
Request example in Python
def upload_document(access_token, filename, content_type='application/pdf'):
url = 'https://api.signicat.com/sign/documents'
document_headers = {
'content-type': content_type,
'authorization': 'Bearer ' + access_token,
}
with open(filename, 'rb') as file:
response = requests.post(url, headers=document_headers, data=file)
return response.json()['documentId']
In the code snippet above, you can see that we're extracting and returning the documentId from the response JSON.
Response example
The full response to the POST request to the Documents endpoint looks like this:
{
"mimeType": "application/pdf",
"documentId": "0197d5cb-d683-7451-9b21-1a2da906b353",
"createdAt": "2025-07-04T14:16:35.202871056Z",
"documentHash": {
"hash": "Y2QyOGVkNGMzZjUwNzU3OWQzMTM4YmRiZjRiOTU0MWViNGQ0MGI2MjAzNGMzNzFlNzg3ZGM1YmU0OGE0MzBlZg==",
"hashAlgorithm": "SHA256"
}
}
If you want to upload a text document instead, just change the content-type header to text/plain.
The document will remain on the server for 30 minutes, after which it will be deleted unless it has been used in a subsequent signing session.
Once you add the document to a signing session, the session determines the document's retention period. By default, documents in a signing session are kept for 45 days.
3. Create a document collection
Once you have uploaded the document, the next step is to create a document collection. A document collection is a logical grouping of documents that will be signed together. This allows you to manage multiple documents in a single signing session.
- For more information on the concepts and terminology of the API, see our Sign API v2 terminology page.
- Learn how to manage multiple documents and signing sessions with document collections in our Document collections feature guide.
In this tutorial, the document collection only has a single document in it. To create the document collection, you make a POST request to the the Document collections endpoint with a JSON structure containing the documentId you obtained in the previous step.
Request example in Python
def create_document_collection(access_token, document_id):
url = 'https://api.signicat.com/sign/document-collections'
document_collection_headers = {
'content-type': 'application/json',
'authorization': 'Bearer ' + access_token,
}
data = {
"documents": [
{
"documentId": f"{document_id}",
}
]
}
response = requests.post(url, headers=document_collection_headers, data=json.dumps(data))
return response.json()['id']
In the code snippet above, you are returning the id of the document collection response, since you'll be needing it in the next step.
Response example
The full response to the POST request to the the Document collections endpoint has the following format:
{
"id": "0197d5cb-dbbd-7e4d-b95c-9f2920882733",
"documents": [
{
"documentId": "0197d5cb-d683-7451-9b21-1a2da906b353"
}
]
}
4. Create a signing session
Equipped with the documentId and the documentCollectionId you previously obtained, you're now ready to create a signing session, which specifies the details for the end-user experience as well as the outcome of the signature process.
To create a signing session, you need to make an HTTP POST request to the Signing sessions endpoint with a JSON structure that includes the documentId and the documentCollectionId. The best way to illustrate how this is done, in its simplest form, is to look at some example code.
Request example in Python
def create_sign_session(access_token, document_collection_id, document_id):
external_reference = str(uuid.uuid4())
url = 'https://api.signicat.com/sign/signing-sessions'
sign_session_headers = {
'content-type': 'application/json',
'authorization': 'Bearer ' + access_token,
}
data = [
{
"title": "The title of the signing session",
"externalReference": f"{external_reference}",
"documents": [
{
"action": "SIGN",
"documentCollectionId": f"{document_collection_id}",
"documentId": f"{document_id}"
}
],
"signingSetup": [
{
"identityProviders": [{
"idpName": "ftn"
}],
"signingFlow": "AUTHENTICATION_BASED"
}
],
"packageTo": ["PADES_CONTAINER"],
"ui": {
"language": "fi",
},
"redirectSettings": {
"error": f"https://www.example.com?q=error&externalReference={external_reference}",
"cancel": f"https://www.example.com?q=cancel&externalReference={external_reference}",
"success": f"https://www.example.com?q=success&externalReference={external_reference}"
}
}
]
response = requests.post(url, headers=sign_session_headers, data=json.dumps(data))
return response.json()[0]['id'], response.json()[0]['signatureUrl']
The following is an explanation of each field and its role in the request:
-
title: All signing sessions must have a title. In certain end-user configurations, this title will be displayed to the end-user. An example of an appropriate title could be "Rental agreement between X and Y". -
externalReference: This field is intended for you to put your own internal identifier on the signing session, so that you can correlate it with the relevant process on your side. Note also that in this example, we're appending the external reference parameter to the redirect URLs so that, when the end-user returns to our application, we will know the context of the signature. -
documents: In our simple one-document scenario, this array contains a single object with three fields:documentCollectionIdanddocumentIdidentify the document.actionspecifies what the end-user is expected to do: Here, it'sSIGN.
-
signingSetup: This array contains the options for the signature process:identityProvidersspecifies which identity providers should be available to choose from for the end-user. If you don't specify this, then all configured identity providers on the account will be shown as options. In our example, we are using Finnish Trust Network (FTN).- In our simple scenario, we set
signingFlowtoAUTHENTICATION_BASED. Other options are available but omitted here for brevity.
NoteYou can find provider-specific integration guides in our ID methods documentation:
-
packageTo: Here, we want the signed document to be a PAdES (PDF Advanced Electronic Signatures), so we set it toPADES_CONTAINER. -
ui: The settings in this object will affect the user interface, for examplelanguage. -
redirectSettings: This object specifies where the end-user should be redirected after signing. It is not mandatory to set redirect URLs. If you do not specify them, the end-user will terminate the signature process at a completion page provided by Signicat.
For more information on all available fields and their purpose, see our Sign API v2 reference.
Response example
The response to the POST request to the the Signing sessions endpoint will be a full JSON structure in the following format:
[
{
"id": "0197d5fb-d3ce-70c0-a420-68972e1c4d57",
"signatureUrl": "https://example.sandbox.signicat.com/sign?sessionId=0197d5fb-d3ce-70c0-a420-68972e1c4d57",
"title": "The title of the signing session",
"dueDate": "2025-08-03T15:09:00.139911468Z",
"documents": [
{
"documentCollectionId": "0197d5fb-d2bd-780a-8102-dd126ad41396",
"action": "SIGN",
"documentId": "0197d5fb-cc53-7514-8f69-df73c879f22c"
}
],
"lifecycle": {
"state": "READY",
"stateIsFinal": false
},
"output": {
"signatures": [],
"packages": []
},
"externalReference": "85950a80-aba0-453d-be77-f75d20adbc9e",
"signingSetup": [
{
"identityProviders": [{ "idpName": "ftn" }],
"signingFlow": "AUTHENTICATION_BASED",
"additionalParameters": {}
}
],
"subsequentTo": [],
"packageTo": [
"PADES_CONTAINER"
],
"ui": {
"language": "fi"
},
"redirectSettings": {
"error": "https://www.example.com?q=error&externalReference=85950a80-aba0-453d-be77-f75d20adbc9e",
"cancel": "https://www.example.com?q=cancel&externalReference=85950a80-aba0-453d-be77-f75d20adbc9e",
"success": "https://www.example.com?q=success&externalReference=85950a80-aba0-453d-be77-f75d20adbc9e"
}
}
]
In our example, we are mostly interested in the signing session id, as well as the signatureUrl which we will use to redirect the end-user. In a real-world application, you would typically store at least the signing session id and the externalReference in a database so that you can correlate them later.
5. Redirect the end-user to the signature application
Once you have created the signing session, you can direct the end-user to the signatureUrl provided in the response. This URL will take them to the signing interface where they can complete (or cancel) the signing process. You then wait for the user to return to your application.
6. Get the result from the signing session
In our example, we would like the signed document to be a signed PDF, a PAdES document. We refer to the process of converting the raw, signed document to a PAdES as packaging, meaning that the document is packaged into a PAdES container for easy viewing in supported PDF readers.
However, packaging is an asynchronous process. This means that when the end-user returns to your application after signing, the PAdES is most likely not produced yet. The time it takes to complete the packaging is not guaranteed, so you should not poll API endpoints to await the result and keep the end-user waiting in the meantime, as the user experience would suffer. Instead, you set up a webhook in order to get notified when packaging has been completed.
Configure a webhook subscription
Setting up a webhook is a simple operation that you manage yourself in the Signicat Dashboard. To learn how to do this, see the Add a subscription section in our Events documentation.
In our example, we have set up a webhook subscription for the events 'Packaging completed' and 'Packaging failed', under the 'Signature' label in the Dashboard.

Example for a webhook subscription for two events
When packaging has completed, our application receives a webhook message with the following payload:
{
"id": "5ddcfab1-31a9-4660-b0b6-63eecebcedfc",
"timestamp": "2025-07-04T15:51:58.8654531Z",
"eventName": "package.completed",
"sender": "signature",
"eventData": {
"id": "0197d5fb-d3ce-70c0-a420-68972e1c4d57",
"externalId": "85950a80-aba0-453d-be77-f75d20adbc9e"
},
"accountId": "a-spge-aCVRlHJKfdhjkhscfd40",
"expiresAt": "2025-07-04T15:53:58.8654527Z",
"isMockEvent": false,
"tags": []
}
Inside the eventData, we find the id, which is the signing session ID and externalId, which is the externalReference. At this point, we will now call the Signing sessions endpoint to retrieve the document ID of the PAdES document and then we will download it.
Retrieve the document ID of the PAdES document
To retrieve the document ID of the PAdES document, you need to make an HTTP GET request to the Signing sessions endpoint using the signing session ID you received in the webhook.
Request example in Python
def get_sign_session(access_token, session_id):
url = f"https://api.signicat.com/sign/signing-sessions/{session_id}"
sign_session_headers = {
'authorization': 'Bearer ' + access_token,
}
response = requests.get(url, headers=sign_session_headers)
sign_session_response = json.loads(response.content)
output = sign_session_response.get('output', {})
packages = output.get('packages', [])
pades = packages[0] if packages else None
pades_document_id = pades.get('resultDocumentId') if pades else None
return pades_document_id
In the code snippet above, shown on lines 11-13, we extract the document ID of the PAdES from the response.
Response example
The response to the GET request to the Signing sessions endpoint is, again, the full signing session data structure, which will now contain updated information regarding the status of the process, as well as the relevant document identifiers.
{
"id": "0197d5fb-d3ce-70c0-a420-68972e1c4d57",
/* REMOVED FOR BREVITY */
"lifecycle": {
"state": "SIGNED",
"stateIsFinal": true
},
"output": {
"signatures": [
{
"resultDocumentId": "0197d623-1dae-7ea6-88f9-8474d83dbf97",
"originalDocumentId": "0197d622-d70d-73de-8e73-d3f742c8d881",
"signatureType": "XADES"
}
],
"packages": [
{
"packageId": "0154e96f-4ff8-448b-bd22-6401cfa13180",
"resultDocumentId": "0197d623-2b90-75e5-be3b-138fe89dfe38",
"packageType": "PADES_CONTAINER"
}
]
},
/* REMOVED FOR BREVITY */
}
7. Download the signed document
All that remains now is to download the PAdES document. To download the PAdES, you need to make an HTTP GET request to the Documents endpoint of the API using the document ID you obtained in the previous step.
Request example in Python
import requests
def download_document(access_token, document_id):
url = f'https://api.signicat.com/sign/documents/{document_id}'
document_headers = {
'authorization': 'Bearer ' + access_token,
}
response = requests.get(url, headers=document_headers)
return response.content
The response contains the binary content of the PAdES document. You can now save it as a PDF file to complete the process.
API reference
Explore our Sign API v2 reference documentation to look up all API endpoints and properties as well as view sample requests and responses.