This guide explains how to integrate Ignisign's electronic signature capabilities directly using the REST API, without using the SDK. The REST API provides complete access to all Ignisign features, allowing you to build custom integrations in any programming language that supports HTTP requests.
Using the direct REST API approach offers several benefits:
All Ignisign API requests require authentication using your API key with a Bearer token:
// Add your API key to request headers
const headers = {
'Authorization': 'Bearer skv2_your_api_key_here',
'Content-Type': 'application/json'
};
async function makeApiRequest(endpoint, method, data = null) {
const response = await fetch(`https://api.ignisign.io/v4/${endpoint}`, {
method,
headers,
...(data && { body: JSON.stringify(data) })
});
if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`);
}
return await response.json();
}
import requests
# Add your API key to request headers
headers = {
'Authorization': 'Bearer skv2_your_api_key_here',
'Content-Type': 'application/json'
}
def make_api_request(endpoint, method='GET', data=None):
url = f'https://api.ignisign.io/v4/{endpoint}'
response = requests.request(
method=method,
url=url,
headers=headers,
json=data
)
response.raise_for_status()
return response.json()
# Example API request with authentication
curl -X POST 'https://api.ignisign.io/v4/signature-requests/one-call-sign' \
-H 'Authorization: Bearer skv2_your_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"title": "Contract signature",
"signatureMethod": "SIMPLE_STD",
"signers": [
{
"email": "[email protected]",
"firstName": "John",
"lastName": "Doe"
}
],
"documents": [
{
"originalName": "contract.pdf",
"mimeType": "application/pdf",
"base64": "JVBERi0xLjcKJb...[Base64 encoded content]"
}
]
}'
You can find your API key in the Ignisign Console under your application's API Keys section. API keys start with skv2_
.
Before creating signature requests, you need to prepare the documents to be signed:
async function uploadDocument(token: string, appId: string, appEnv: string, documentFile: File) {
const formData = new FormData();
formData.append('document', documentFile);
const response = await fetch(`https://api.ignisign.io/v4/applications/${appId}/envs/${appEnv}/documents`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData
});
if (!response.ok) {
throw new Error(`Document upload failed: ${response.statusText}`);
}
return await response.json();
}
import requests
def upload_document(token, app_id, app_env, document_path):
with open(document_path, 'rb') as file:
response = requests.post(
f'https://api.ignisign.io/v4/applications/{app_id}/envs/{app_env}/documents',
headers={
'Authorization': f'Bearer {token}'
},
files={
'document': file
}
)
response.raise_for_status()
return response.json()
curl -X POST 'https://api.ignisign.io/v4/applications/your_app_id/envs/DEVELOPMENT/documents' \
-H 'Authorization: Bearer your_jwt_token' \
-F 'document=@/path/to/your/document.pdf'
Ignisign provides a "one-call-sign" endpoint that simplifies creating signature requests with all necessary components:
async function createSignatureRequest(token: string, requestData) {
const response = await fetch('https://api.ignisign.io/v4/signature-requests/one-call-sign', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
});
if (!response.ok) {
throw new Error(`Signature request creation failed: ${response.statusText}`);
}
return await response.json();
}
// Example request data
const signatureRequestData = {
title: "Contract signature",
signatureMethod: "SIMPLE_STD",
signers: [
{
email: "[email protected]",
firstName: "John",
lastName: "Doe"
}
],
documents: [
{
originalName: "contract.pdf",
mimeType: "application/pdf",
base64: "JVBERi0xLjcKJb...[Base64 encoded content]"
}
]
};
import requests
import base64
def create_signature_request(token, request_data):
response = requests.post(
'https://api.ignisign.io/v4/signature-requests/one-call-sign',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json=request_data
)
response.raise_for_status()
return response.json()
# Example request data
signature_request_data = {
"title": "Contract signature",
"signatureMethod": "SIMPLE_STD",
"signers": [
{
"email": "[email protected]",
"firstName": "John",
"lastName": "Doe"
}
],
"documents": [
{
"originalName": "contract.pdf",
"mimeType": "application/pdf",
"base64": "JVBERi0xLjcKJb...[Base64 encoded content]"
}
]
}
# Helper function to encode a PDF file to base64
def encode_pdf_to_base64(file_path):
with open(file_path, "rb") as pdf_file:
return base64.b64encode(pdf_file.read()).decode('utf-8')
curl -X POST 'https://api.ignisign.io/v4/signature-requests/one-call-sign' \
-H 'Authorization: Bearer your_jwt_token' \
-H 'Content-Type: application/json' \
-d '{
"title": "Contract signature",
"signatureMethod": "SIMPLE_STD",
"signers": [
{
"email": "[email protected]",
"firstName": "John",
"lastName": "Doe"
}
],
"documents": [
{
"originalName": "contract.pdf",
"mimeType": "application/pdf",
"base64": "JVBERi0xLjcKJb...[Base64 encoded content]"
}
]
}'
You can check the status of signature requests to track their progress:
async function getSignatureRequestsStatus(token: string, appId: string, appEnv: string, signatureRequestIds: string[]) {
const response = await fetch(`https://api.ignisign.io/v4/applications/${appId}/envs/${appEnv}/signature-requests/status`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
signatureRequestIds
})
});
if (!response.ok) {
throw new Error(`Failed to get status: ${response.statusText}`);
}
return await response.json();
}
import requests
def get_signature_requests_status(token, app_id, app_env, signature_request_ids):
response = requests.post(
f'https://api.ignisign.io/v4/applications/{app_id}/envs/{app_env}/signature-requests/status',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json={
'signatureRequestIds': signature_request_ids
}
)
response.raise_for_status()
return response.json()
curl -X POST 'https://api.ignisign.io/v4/applications/your_app_id/envs/DEVELOPMENT/signature-requests/status' \
-H 'Authorization: Bearer your_jwt_token' \
-H 'Content-Type: application/json' \
-d '{
"signatureRequestIds": ["signature_request_id_1", "signature_request_id_2"]
}'
Managing signers is a key part of the signature process:
// Check if signers can be added to a signature request
async function checkSignersCanBeAdded(token: string, signatureRequestId: string, emails: string[]) {
const response = await fetch(`https://api.ignisign.io/v4/signature-requests/${signatureRequestId}/check-signers-can-be-added`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
emails
})
});
if (!response.ok) {
throw new Error(`Failed to check signers: ${response.statusText}`);
}
return await response.json();
}
// Resend email to a signer
async function resendSignatureRequestEmail(token: string, signatureRequestId: string, signerId: string) {
const response = await fetch(`https://api.ignisign.io/v4/signature-requests/${signatureRequestId}/${signerId}/resend-email`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error(`Failed to resend email: ${response.statusText}`);
}
return await response.json();
}
import requests
# Check if signers can be added to a signature request
def check_signers_can_be_added(token, signature_request_id, emails):
response = requests.post(
f'https://api.ignisign.io/v4/signature-requests/{signature_request_id}/check-signers-can-be-added',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json={
'emails': emails
}
)
response.raise_for_status()
return response.json()
# Resend email to a signer
def resend_signature_request_email(token, signature_request_id, signer_id):
response = requests.post(
f'https://api.ignisign.io/v4/signature-requests/{signature_request_id}/{signer_id}/resend-email',
headers={
'Authorization': f'Bearer {token}'
}
)
response.raise_for_status()
return response.json()
# Check if signers can be added
curl -X POST 'https://api.ignisign.io/v4/signature-requests/your_signature_request_id/check-signers-can-be-added' \
-H 'Authorization: Bearer your_jwt_token' \
-H 'Content-Type: application/json' \
-d '{
"emails": ["[email protected]"]
}'
# Resend email to a signer
curl -X POST 'https://api.ignisign.io/v4/signature-requests/your_signature_request_id/your_signer_id/resend-email' \
-H 'Authorization: Bearer your_jwt_token'
Webhooks allow your application to receive real-time updates about signature events:
// Add a webhook endpoint to your application
async function addWebhookEndpoint(token: string, appId: string, appEnv: string, endpointData) {
const response = await fetch(`https://api.ignisign.io/v4/applications/${appId}/envs/${appEnv}/webhooks/endpoints`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(endpointData)
});
if (!response.ok) {
throw new Error(`Failed to add webhook: ${response.statusText}`);
}
return await response.json();
}
// Example webhook endpoint data
const webhookEndpointData = {
url: "https://your-app.com/webhooks/ignisign",
topics: ["SIGNATURE_REQUEST", "SIGNATURE"],
description: "Main webhook endpoint"
};
// Example webhook handler implementation
function handleWebhookEvent(req, res) {
const eventData = req.body;
// Verify webhook authenticity
// Implement your verification logic here
// Process different event types
switch(eventData.topic) {
case "SIGNATURE_REQUEST":
handleSignatureRequestEvent(eventData);
break;
case "SIGNATURE":
handleSignatureEvent(eventData);
break;
default:
console.log("Unknown webhook event type:", eventData.topic);
}
// Acknowledge receipt
res.status(200).send();
}
import requests
from flask import Flask, request, jsonify
# Add a webhook endpoint to your application
def add_webhook_endpoint(token, app_id, app_env, endpoint_data):
response = requests.post(
f'https://api.ignisign.io/v4/applications/{app_id}/envs/{app_env}/webhooks/endpoints',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json=endpoint_data
)
response.raise_for_status()
return response.json()
# Example webhook endpoint data
webhook_endpoint_data = {
"url": "https://your-app.com/webhooks/ignisign",
"topics": ["SIGNATURE_REQUEST", "SIGNATURE"],
"description": "Main webhook endpoint"
}
# Example Flask webhook handler implementation
app = Flask(__name__)
@app.route('/webhooks/ignisign', methods=['POST'])
def handle_webhook_event():
event_data = request.json
# Verify webhook authenticity
# Implement your verification logic here
# Process different event types
if event_data.get('topic') == "SIGNATURE_REQUEST":
handle_signature_request_event(event_data)
elif event_data.get('topic') == "SIGNATURE":
handle_signature_event(event_data)
else:
print(f"Unknown webhook event type: {event_data.get('topic')}")
# Acknowledge receipt
return jsonify({"status": "ok"}), 200
# Add a webhook endpoint
curl -X POST 'https://api.ignisign.io/v4/applications/your_app_id/envs/DEVELOPMENT/webhooks/endpoints' \
-H 'Authorization: Bearer your_jwt_token' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://your-app.com/webhooks/ignisign",
"topics": ["SIGNATURE_REQUEST", "SIGNATURE"],
"description": "Main webhook endpoint"
}'
After signatures are completed, you can download the proof documents:
async function downloadSignatureProof(token: string, documentId: string, signatureType: string) {
const response = await fetch(`https://api.ignisign.io/v4/documents/${documentId}/signature-type/${signatureType}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error(`Failed to download proof: ${response.statusText}`);
}
// Return the binary stream
return await response.blob();
}
// Save the proof to a file
async function saveProofToFile(proof, filename) {
const url = window.URL.createObjectURL(proof);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}
// Usage example
async function getAndSaveProof(token, documentId) {
const proof = await downloadSignatureProof(token, documentId, 'PDF_WITH_SIGNATURES');
await saveProofToFile(proof, `proof-${documentId}.pdf`);
}
import requests
def download_signature_proof(token, document_id, signature_type):
response = requests.get(
f'https://api.ignisign.io/v4/documents/{document_id}/signature-type/{signature_type}',
headers={
'Authorization': f'Bearer {token}'
},
stream=True
)
response.raise_for_status()
return response.content
# Save the proof to a file
def save_proof_to_file(proof_content, filename):
with open(filename, 'wb') as f:
f.write(proof_content)
# Usage example
def get_and_save_proof(token, document_id):
proof = download_signature_proof(token, document_id, 'PDF_WITH_SIGNATURES')
save_proof_to_file(proof, f'proof-{document_id}.pdf')
# Download a signature proof
curl -X GET 'https://api.ignisign.io/v4/documents/your_document_id/signature-type/PDF_WITH_SIGNATURES' \
-H 'Authorization: Bearer your_jwt_token' \
--output proof.pdf
Here are some common issues and their solutions when working with the Ignisign REST API:
- Make sure your API credentials (appId, appEnv, secret) are correct
- Check that your JWT token hasn't expired
- Ensure you're using the correct environment (DEVELOPMENT vs PRODUCTION)
- Validate your JSON payloads against the API specification
- Check for missing required fields or incorrect data types
- Ensure all IDs (documentId, signerId, etc.) are valid
- Verify your webhook endpoint is publicly accessible
- Ensure proper error handling in your webhook receiver
- Implement retry logic for processing webhook events
Implement proper error handling in your requests:
// Example error handling
async function apiRequest(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error (${response.status}): ${errorData.message || response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
// Handle specific error types
if (error.message.includes('401')) {
// Handle authentication error
refreshToken();
}
throw error;
}
}
import requests
# Example error handling
def api_request(url, method='GET', **kwargs):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as http_err:
error_data = {}
try:
error_data = response.json()
except:
pass
error_message = error_data.get('message', str(http_err))
print(f"API Error ({response.status_code}): {error_message}")
# Handle specific error types
if response.status_code == 401:
# Handle authentication error
refresh_token()
raise
except Exception as err:
print(f"Request failed: {err}")
raise
Now that you understand how to integrate with Ignisign's REST API, you can:
- Explore Advanced Features:
- Implement custom signature workflows
- Add multi-factor authentication for signers
- Integrate with your document management system
- Optimize Your Integration:
- Implement caching strategies for tokens and frequently used data
- Add monitoring and logging for API requests
- Develop comprehensive error handling
- Consider Compliance Requirements:
- Ensure your integration meets regulatory requirements (eIDAS, ESIGN, etc.)
- Implement appropriate data retention policies
- Document your signature processes for compliance audits
For more information, refer to the complete API reference or contact Ignisign support for assistance with your specific integration needs.