8. Document Signing and Sealing
Document Signing and Sealing
This scenario demonstrates how to create a document, apply electronic signatures or seals, and download the completed file. Digital signatures and seals provide authenticity, integrity, and non-repudiation for your documents.
Key features:
Create a document from an uploaded PDF file
Apply an electronic seal (certification) to the document
Add a visual signature with positioning on specific pages
Download the signed or sealed document
Download the document's audit trail for compliance and verification purposes
Prerequisites
Before signing or sealing a document, you need:
A valid authentication token (see the "Authentication & Security" section for details)
A PDF file to upload and sign
Appropriate permissions to sign documents in your Circularo instance
For visual signatures, a signature image file already uploaded to your account
Step 1 - Upload a PDF file
Before creating a document, you need to upload the PDF file that will serve as the document content. This step uploads and stores a PDF file in the Circularo system.
The file is uploaded as a multipart/form-data request
The response includes the file ID that will be used in the document creation step
The response also includes storage quota information to help manage available space
The file upload is a separate step from document creation and signing.
Endpoint
POST /files/saveFile
Request
POST /files/saveFile?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Content-Type: multipart/form-data
{
"file": "blob",
"fileName": "Contract Agreement"
}
Response
The response contains the following important properties:
fileHash - Located at
file.idin the response.Example value:
iS8Gu6vWgX7bu34ywE0ObWmt8kwOoq4wz5RtCggJI7oaXRA5j4adGFvoB63rhNzR
The PDF file has been successfully uploaded and stored in the system. The response includes the file ID that will be used in the next step to create a document based on this file.
The file.id is the unique identifier for the uploaded file
This ID will be used in the document creation step to reference this file
The storage information shows your current usage and available quota
Store the file ID for use in the next step. This ID is required to create a document based on this file.
Step 2 - Create a document from the PDF file
This endpoint creates a new document in the Circularo system using the previously uploaded PDF file.
The documentType parameter specifies which metadata definition to use
The workflow parameter defines the workflow that will be applied to the document
The definitionType parameter is set to "ext" to indicate an external file-based document
The pdfFile.content parameter references the file ID from the previous step
The document must be created before it can be signed or sealed.
Endpoint
POST /documents
Request
POST /documents?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Content-Type: application/json
{
"body": {
"documentType": "d_default",
"documentTitle": "My Document",
"pdfFile": {
"content": "iS8Gu6vWgX7bu34ywE0ObWmt8kwOoq4wz5RtCggJI7oaXRA5j4adGFvoB63rhNzR"
}
},
"definitionType": "ext",
"workflow": "wf_archive"
}
Response
The response contains the following important properties:
documentId - Located at
results[0].documentIdin the response.Example value:
c77ac248-155b-4f6e-ac00-d2093162cb03
The document has been successfully created and is now available in the system.
The response includes the document ID which will be used for signing or sealing
The document is created with the specified metadata definition and workflow
The document is initially in the first state of the specified workflow
Store the document ID for use in the subsequent steps.
Step 3 - Retrieve document information
Before signing or sealing a document, you need to retrieve its current version. This step fetches the document information using the document ID.
The document ID uniquely identifies the document in the system
The response includes the current document version, which is required for signing operations
Version information prevents conflicts when multiple users are working with the same document
The document version is critical for signing operations. If you use an outdated version, the operation will fail with a 409 Conflict error.
Endpoint
GET /documents/:documentId
Request
GET /documents/c77ac248-155b-4f6e-ac00-d2093162cb03?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Response
The response contains the following important properties:
documentVersion - Located at
results[0]._versionin the response.Example value:
5
The response includes comprehensive information about the document, including its current version.
The _version field contains the current document version needed for signing operations
This version number changes whenever the document is modified
If a signing operation fails with a version mismatch error, retrieve the document again to get the updated version
If any signing operation fails with a 409 Conflict error, call this endpoint again to get the updated document version. Background tasks may change the document version after it is created.
Step 4A - Seal the document
This endpoint applies an electronic seal (certification) to the document. Sealing a document certifies its authenticity and integrity without adding a visual signature.
The documentVersion parameter must match the current version of the document
The id parameter specifies which document to seal
The certificate parameter set to true applies a digital certificate to the document
Sealing is appropriate when you need to certify a document's authenticity without adding a visual signature. It applies cryptographic protection to the entire document.
Endpoint
PUT /documents/seal/:documentVersion
Path parameters:
documentVersion - Document version taken from the previous step.
Request
PUT /documents/seal/5?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Content-Type: application/json
{
"id": "c77ac248-155b-4f6e-ac00-d2093162cb03",
"certificate": true
}
The document has been successfully sealed with a digital certificate.
The document now has cryptographic protection that verifies its integrity
The seal is applied to the entire document
The document's workflow history is updated to reflect the sealing operation
Sealed documents can be verified by PDF readers that support digital signatures.
Step 4B - Sign the document
This endpoint applies a visual signature to the document at a specified position. Signing can add both a visual representation of your signature and cryptographic protection (depending on system settings).
The documentVersion parameter must match the current version of the document
The signatures array contains information about where and how to place the signature
The position object defines the exact placement of the signature on the page
The blob parameter references your signature image file
Endpoint
PUT /documents/sign/:documentVersion
Path parameters:
documentVersion - Document version taken from the previous step.
Request
PUT /documents/sign/5?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Content-Type: application/json
{
"signatures": [
{
"pages": [ //Page(s) where the signature should be placed
1
],
"position": { //Position and size of the signature
"percentX": 0.5336425978217023,
"percentY": 0.2360980475986889,
"percentWidth": 0.3910665378654381,
"percentHeight": 0.1
},
"blob": "T1jzK5kcA8v2T89uwZQ6s4pDGti7xdeRo2dpk4z6CrdQGxVtmcJroSbDCEcqaN3y", //Signature image file ID
"decorationType": "empty",
"type": "signature", //Other possible types: initials, stamp, wacom, annotation, and image
"timestamp": false //If true, places timestamp under the signature
}
],
"id": "c77ac248-155b-4f6e-ac00-d2093162cb03" //ID of the document you want to sign
}
The document has been successfully signed with your signature image.
The signature is visually placed at the specified position on the document
Depending on the system settings, the document now may have a cryptographic protection that verifies its integrity
The document's workflow history is updated to reflect the signing operation
You can add multiple signatures to a document by including more objects in the signatures array.
Step 5 - Retrieve updated document information after signing/sealing
After signing or sealing a document, the file ID (hash) changes because a new version of the document has been created. This step fetches the updated document information to get the new file hash needed for downloading.
The document ID remains the same, but the file content has been updated with signatures or seals
The response includes the new file hash (pdfFile.content) that must be used for downloading
This step is crucial because the original file hash no longer points to the signed/sealed version
Skipping this step will result in downloading the original unsigned document instead of the signed/sealed version.
Endpoint
GET /documents/:documentId
Request
GET /documents/c77ac248-155b-4f6e-ac00-d2093162cb03?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
Response
The response contains the following important properties:
fileHash - Located at
results[0].pdfFile.contentin the response.Example value:
iivep6vKkrnrt77yTR0K2pOgVWEKtyipPkBNeu6cEFu6JgNGHCidScg7H9y1v5QJ
The response includes the updated document information with the new file hash for the signed/sealed document.
The pdfFile.content field contains the new file hash for the signed/sealed document
This new hash is different from the original file hash used to create the document
The new hash must be used in the next step to download the signed/sealed version of the document
Always retrieve the document information after signing or sealing to get the updated file hash. The original file hash will only download the unsigned version of the document.
Step 6 - Download the signed or sealed document
This endpoint downloads the signed or sealed document file using the new file hash obtained in the previous step.
The hash parameter must be the new file hash obtained after signing/sealing
Using the original file hash would download the unsigned version of the document
The response is the binary content of the document file with signatures or seals applied
The downloaded document can be opened in any PDF reader. Digital signatures and seals can be verified in PDF readers that support this feature.
Endpoint
GET /files/loadFile/hash/:hash
Path parameters:
hash - The new file hash obtained after signing/sealing the document.
Request
GET /files/loadFile/hash/iivep6vKkrnrt77yTR0K2pOgVWEKtyipPkBNeu6cEFu6JgNGHCidScg7H9y1v5QJ?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
The signed or sealed document has been successfully downloaded.
The response contains the binary content of the document file with signatures or seals applied
The file includes all visual signatures and/or cryptographic protections that were applied
The document can be saved locally or processed further as needed
Step 7 - Download the audit trail
This endpoint downloads a PDF document containing the complete audit trail for the signed or sealed document. The audit trail provides a detailed record of all actions performed on the document, including creation, modifications, and signatures.
The audit trail is essential for compliance and verification purposes
It contains timestamps, user information, and details of all actions performed on the document
The audit trail is generated as a separate PDF document that can be stored alongside the signed document
This provides a complete chain of custody and evidence of the document's integrity
The audit trail is particularly important in regulated industries and for legally sensitive documents where proof of document handling may be required.
Endpoint
GET /documents/:documentId/audit
Request
GET /documents/c77ac248-155b-4f6e-ac00-d2093162cb03/audit?token=E7yTzUxBPDpwgj5sKGyfFjTf8ZJvxH6EA1M4jMGkTy8NmevThY3eifw5c5q96hAi
The audit trail PDF has been successfully downloaded.
The response contains the binary content of the audit trail PDF
This document provides a complete record of all actions performed on the document
The audit trail can be saved locally for record-keeping and compliance purposes
Store the audit trail alongside the signed document for a complete record of the document's lifecycle.
Document Signing and Sealing Summary
You have successfully learned how to create, sign or seal, and download documents in the Circularo system.
Key Concepts
Document Sealing: Applies certification to the entire document without visual elements
Document Signing: Adds a visual signature at specific locations with cryptographic protection (optional)
Version Control: Document version is required to prevent conflicts during signing operations
Digital Certificates: Cryptographic protection that verifies document integrity and authenticity
Audit Trail: Comprehensive record of all document activities for compliance and verification
Choosing Between Signing and Sealing
Use Sealing When: You need to certify a document's authenticity without visual signatures
Use Signing When: You need visual representation of signatures at specific locations
Example Implementation
See our OpenAPI documentation to learn about the full set of API endpoints and parameters.
Please use proper exception handling and function decomposition in your own code. The code is provided for illustrative purposes only and is not intended for production use.
// Document signing example
const URL = "https://sandbox.circularo.com";
const API_PATH = "/api/v1";
const TOKEN = "YOUR_AUTH_TOKEN"; // Obtained from login or API key
const SIGNATURE_IMAGE_ID = "YOUR_SIGNATURE_IMAGE_ID"; // File ID of your uploaded signature image
try {
// Step 1: Upload a PDF file
const formData = new FormData();
formData.append('fileName', 'Contract Agreement');
formData.append('file', fs.createReadStream('path/to/document.pdf')); // Using Node.js fs module
const uploadResponse = await fetch(`${URL}${API_PATH}/files/saveFile?token=${TOKEN}`, {
method: 'POST',
body: formData
});
if (!uploadResponse.ok) {
throw new Error(`File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`);
}
const uploadData = await uploadResponse.json();
const fileId = uploadData.file.id;
// Step 2: Create a document from the uploaded file
const createResponse = await fetch(`${URL}${API_PATH}/documents?token=${TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
body: {
documentType: "d_default",
documentTitle: "Contract Agreement",
pdfFile: {
content: fileId
}
},
definitionType: "ext",
workflow: "wf_archive"
})
});
if (!createResponse.ok) {
throw new Error(`Document creation failed: ${createResponse.status} ${createResponse.statusText}`);
}
const createData = await createResponse.json();
const documentId = createData.results[0].documentId;
// Step 3: Get the document version
const documentResponse = await fetch(`${URL}${API_PATH}/documents/${documentId}?token=${TOKEN}`);
if (!documentResponse.ok) {
throw new Error(`Failed to retrieve document: ${documentResponse.status} ${documentResponse.statusText}`);
}
const documentData = await documentResponse.json();
const documentVersion = documentData.results[0]._version;
// Step 4: Option A - Seal the document
const sealResponse = await fetch(`${URL}${API_PATH}/documents/seal/${documentVersion}?token=${TOKEN}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: documentId,
certificate: true
})
});
if (!sealResponse.ok) {
throw new Error(`Document sealing failed: ${sealResponse.status} ${sealResponse.statusText}`);
}
// OR Step 4: Option B - Sign the document
/*
const signResponse = await fetch(`${URL}${API_PATH}/documents/sign/${documentVersion}?token=${TOKEN}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
signatures: [{
pages: [1],
position: {
percentX: 0.5336425978217023,
percentY: 0.2360980475986889,
percentWidth: 0.3910665378654381,
percentHeight: 0.1
},
blob: SIGNATURE_IMAGE_ID,
decorationType: "empty",
type: "signature",
timestamp: false
}],
id: documentId
})
});
if (!signResponse.ok) {
throw new Error(`Document signing failed: ${signResponse.status} ${signResponse.statusText}`);
}
*/
// Step 5: Get the updated document information to obtain the new file hash
const updatedDocumentResponse = await fetch(`${URL}${API_PATH}/documents/${documentId}?token=${TOKEN}`);
if (!updatedDocumentResponse.ok) {
throw new Error(`Failed to retrieve updated document: ${updatedDocumentResponse.status} ${updatedDocumentResponse.statusText}`);
}
const updatedDocumentData = await updatedDocumentResponse.json();
const newFileId = updatedDocumentData.results[0].pdfFile.content;
// Step 6: Download the signed/sealed document using the new file hash
const downloadResponse = await fetch(`${URL}${API_PATH}/files/loadFile/hash/${newFileId}?token=${TOKEN}`);
if (!downloadResponse.ok) {
throw new Error(`Document download failed: ${downloadResponse.status} ${downloadResponse.statusText}`);
}
// Save the document to disk or process it as needed
const fileBlob = await downloadResponse.blob();
const downloadLink = document.createElement('a');
downloadLink.href = URL.createObjectURL(fileBlob);
downloadLink.download = 'Signed_Contract.pdf';
downloadLink.click();
// Step 7: Download the audit trail
const auditTrailResponse = await fetch(`${URL}${API_PATH}/documents/${documentId}/audit?token=${TOKEN}`);
if (!auditTrailResponse.ok) {
throw new Error(`Audit trail download failed: ${auditTrailResponse.status} ${auditTrailResponse.statusText}`);
}
// Save the audit trail to disk
const auditTrailBlob = await auditTrailResponse.blob();
const auditTrailLink = document.createElement('a');
auditTrailLink.href = URL.createObjectURL(auditTrailBlob);
auditTrailLink.download = 'Contract_Audit_Trail.pdf';
auditTrailLink.click();
console.log('Document and audit trail successfully downloaded');
} catch (error) {
console.error('Error in document signing process:', error.message);
}
Digital signatures and seals have legal implications. Ensure you understand the legal requirements in your jurisdiction before implementing electronic signatures in production systems.