Introduction
The Inkless API lets you programmatically create and send signing links (“envelopes”) based on your email templates and document templates, with signing order, merge fields, auditing, and expiry. To get started you must create an API Token, to do this you can browse to Admin -> Company then click on the API Details Tab, Once their type a description in the input box and click "Create Token". Copy the token and store it in a secure place as this will not be shown again and will require you to revoke the token and create a new one if lost.
email_template_id and all document_template_id values must belong to the same company as the token.
API Endpoints
Production Endpoint
https://inkless.co.uk/api/service.php
Development Endpoint
https://inkless.co.uk/api/service.php
Authentication
To access the API, you must include your API token in the Authorization header:
Header
Authorization: Bearer YOUR_API_TOKEN
API Token Format
The API token must follow the format:
ink_live_key.secret
keyis a unique identifier for the key (8-16 alphanumeric characters)secretis the secret key (20+ alphanumeric characters)
Authentication Flow
When you send a request with the API token in the Authorization header, the following steps occur:
- The token is extracted and validated against the expected format.
- If the token does not match the expected format, a 401 Unauthorized error is returned.
- The system checks if the token is valid and not revoked. If the token is revoked or invalid, a 401 Unauthorized error is returned.
- The system checks if the token has expired. If the token is expired, a 401 Unauthorized error is returned.
- The system verifies that the provided HMAC matches the stored HMAC. If it does not match, a 401 Unauthorized error is returned.
- If all checks pass, the request proceeds and the token data is returned for use in subsequent operations.
Response Codes
The following error codes may be returned during the authentication process:
Rate Limiting
Each API token is subject to rate limiting based on the following parameters:
- Limit: The maximum number of requests allowed within a specified time window.
- Window: The time period within which requests are counted.
If the rate limit is exceeded, a 429 Too Many Requests error will be returned. The rate_limit_limit and rate_limit_window values are provided as part of the token data.
Last Used IP
The IP address associated with the API token is updated each time the token is used. The system tracks this and logs the IP in case of misuse or troubleshooting.
Get Balance
/api/get_balance
Each document sent (after being combined) will deduct from your overall balance.
For example: If 1 envelope with 2 documents priced at £0.70 is sent, it will cost £1.40. If the payload has a combine: 1 for both documents, they will be combined into one document, costing you only £0.70.
Response Codes
Response Example
{
"ok":true,
"company_id":127,
"balance":"£0.50",
"as_of":"2025-10-13T15:51:23+00:00"
}
Errors
If the company does not exist or the API token is invalid, a 404 Not Found error will be returned with the message "company not found".
How to Request the Balance
To retrieve the balance for a company, send a POST request to /api/get_balance with the API token in the Authorization header. The request will return the company's wallet balance and the date and time the balance was last updated.
curl -sS -X POST "https://inkless.co.uk/api/get_balance" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json"
$h = @{ Authorization = "Bearer YOUR_API_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/get_balance" `
-Headers $h -ContentType "application/json"
const res = await fetch("https://inkless.co.uk/api/get_balance", {
method:"POST",
headers:{Authorization:"Bearer YOUR_API_TOKEN","Content-Type":"application/json"}
});
console.log(await res.json());
<?php
$ch = curl_init("https://inkless.co.uk/api/get_balance");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN","Content-Type":"application/json"],
]);
echo curl_exec($ch); curl_close($ch);
import requests, json
r = requests.post("https://inkless.co.uk/api/get_balance",
headers={"Authorization":"Bearer YOUR_API_TOKEN","Content-Type":"application/json"})
print(r.json())
Limitations
The endpoint currently does not allow you to directly modify your balance. It only provides the current balance associated with the authenticated company.
Get Document Templates
/api/get_documents
This endpoint retrieves the document templates associated with your company. It returns a list of available templates for your account. If you're working in the sandbox environment, predefined templates will be returned.
Response Codes
Response Example
{
"ok":true,
"documents":[
{
"id":1,
"name":"template 1"
},
{
"id":2,
"name":"template 2"
}
]
}
How to Request Document Templates
To retrieve document templates, send a POST request to /api/get_documents with your API token in the Authorization header. If you're working in the sandbox environment, you will receive predefined templates.
curl -sS -X POST "https://inkless.co.uk/api/get_documents" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json"
$h = @{ Authorization = "Bearer YOUR_API_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/get_documents" `
-Headers $h -ContentType "application/json"
const res = await fetch("https://inkless.co.uk/api/get_documents", {
method:"POST",
headers:{Authorization:"Bearer YOUR_API_TOKEN","Content-Type":"application/json"}
});
console.log(await res.json());
<?php
$ch = curl_init("https://inkless.co.uk/api/get_documents");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN","Content-Type":"application/json"],
]);
echo curl_exec($ch); curl_close($ch);
import requests, json
r = requests.post("https://inkless.co.uk/api/get_documents",
headers={"Authorization":"Bearer YOUR_API_TOKEN","Content-Type":"application/json"})
print(r.json())
Get Email Templates
/api/get_emails
This endpoint retrieves the email templates associated with your company. It returns a list of available email templates for your account. If you're working in the sandbox environment, predefined templates will be returned.
Response Codes
Response Example
{
"ok":true,
"templates":[
{
"id":1,
"name":"document 1"
},
{
"id":2,
"name":"document 2"
}
]
}
How to Request Email Templates
To retrieve email templates, send a POST request to /api/get_emails with your API token in the Authorization header. If you're working in the sandbox environment, you will receive predefined templates.
curl -sS -X POST "https://inkless.co.uk/api/get_emails" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json"
$h = @{ Authorization = "Bearer YOUR_API_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/get_emails" `
-Headers $h -ContentType "application/json"
const res = await fetch("https://inkless.co.uk/api/get_emails", {
method:"POST",
headers:{Authorization:"Bearer YOUR_API_TOKEN","Content-Type":"application/json"}
});
console.log(await res.json());
<?php
$ch = curl_init("https://inkless.co.uk/api/get_emails");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN","Content-Type":"application/json"],
]);
echo curl_exec($ch); curl_close($ch);
import requests, json
r = requests.post("https://inkless.co.uk/api/get_emails",
headers={"Authorization":"Bearer YOUR_API_TOKEN","Content-Type":"application/json"})
print(r.json())
Send Secure Links (Envelope)
/api/send_link
This API endpoint creates secure signing links for each recipient, attaches the specified documents, emails the first signing group, and logs the process for audit purposes. Each recipient receives an email with their specific link, and the next recipient in the list is notified once the previous recipient has signed.
curl -sS -X POST "https://inkless.co.uk/api/send_link" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "send_link",
"email_template_id": 21,
"documents": [
{
"document_template_id": 5,
"merge": {"first_name": "Joe", "start_date": "2025-09-04"},
"recipients": [
{"recipient_number": 1, "name": "Joe Blogs", "email": "Joe@example.com", "phone": "07841939203"},
{"recipient_number": 2, "name": "Manager", "email": "manager@example.com"}
]
}
]
}'
$body = @{
type = "send_link"; email_template_id = 21;
documents = @(@{
document_template_id = 5
merge = @{ first_name = "Joe"; start_date = "2025-09-04" }
recipients = @(
@{ recipient_number=1; name="Joe Blogs"; email="Joe@example.com"; phone="07841939203" },
@{ recipient_number=2; name="Manager"; email="manager@example.com" }
)
})
} | ConvertTo-Json -Depth 10 -Compress
Invoke-RestMethod -Method POST -Uri "https://inkless.co.uk/api/send_link" `
-Headers @{ Authorization = "Bearer YOUR_API_TOKEN" } `
-ContentType "application/json" -Body $body
const res = await fetch("https://inkless.co.uk/api/send_link", {
method:"POST",
headers:{Authorization:"Bearer YOUR_API_TOKEN","Content-Type":"application/json"},
body: JSON.stringify({
type:"send_link", email_template_id:21,
documents:[{
document_template_id:5,
merge:{first_name:"Joe",start_date:"2025-09-04"},
recipients:[
{recipient_number:1,name:"Joe Blogs",email:"Joe@example.com",phone:"07841939203"},
{recipient_number:2,name:"Manager", email:"manager@example.com"}
]
}]
})
});
console.log(await res.json());
<?php
$payload = [
"type"=>"send_link","email_template_id"=>21,
"documents"=>[[
"document_template_id"=>5,
"merge"=>["first_name"=>"Joe","start_date"=>"2025-09-04"],
"recipients"=>[
["recipient_number"=>1,"name"=>"Joe Blogs","email"=>"Joe@example.com","phone"=>"07841939203"],
["recipient_number"=>2,"name"=>"Manager","email"=>"manager@example.com"]
]
]]
];
$ch = curl_init("https://inkless.co.uk/api/send_link");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
echo curl_exec($ch); curl_close($ch);
import requests, json
payload = {
"type":"send_link","email_template_id":21,
"documents":[{
"document_template_id":5,
"merge":{"first_name":"Joe","start_date":"2025-09-04"},
"recipients":[
{"recipient_number":1,"name":"Joe Blogs","email":"Joe@example.com","phone":"07841939203"},
{"recipient_number":2,"name":"Manager","email":"manager@example.com"}
]
}]
}
r = requests.post("https://inkless.co.uk/api/send_link",
headers={"Authorization":"Bearer YOUR_API_TOKEN","Content-Type":"application/json"},
data=json.dumps(payload))
print(r.json())
The earliest signing group (lowest recipient_number) is emailed immediately; subsequent signers are notified automatically after prior completion. If you provide a base64-encoded document, this can be used in place of a document template.
Request Payload Schema
Below is the detailed structure of the request payload for the send_link endpoint, with annotations on which fields are required and which are user-defined.
Root Schema
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Always "send_link" |
email_template_id | integer | Yes | ID of the email template to use |
documents | array | Yes | An array of documents to send, each having its own structure up to 10 documents in a single envelope. |
reference_id / client_reference_id | string | No | Your external reference to store alongside the envelope |
email_reminders | boolean | No | Override company default for reminder emails (1/0) |
email_completed_pdf | boolean | No | Override company default for sending completed PDFs to recipients (1/0) |
enforce_routing_order | boolean | No | When true, recipients are notified sequentially by recipient_number |
Documents Schema
| Field | Type | Required | Description |
|---|---|---|---|
document_template_id | integer | Yes* | ID of the document template. Required unless using replacement_file_base64. |
replacement_file_base64 | string | No* | Base64-encoded PDF/DOCX to use instead of a template. |
replacement_file_name | string | No | Filename to use when uploading a replacement file. |
combine | integer | No | Group documents to merge together (e.g., 1,2,...). All docs with the same combine value are merged. |
require_one | boolean | No | Set to 1 to mark this doc “either/or” (only one signer in the group must sign). |
merge | object | No | Merge fields for dynamic content (names, dates, etc.). |
recipients | array | Yes | List of recipients for this document. |
Recipients Schema
| Field | Type | Required | Description |
|---|---|---|---|
recipient_number | integer | Yes | Recipient's signing order |
name | string | Yes | Recipient's name |
email | string | Yes | Recipient's email address |
phone | string | No | Recipient's phone number (for SMS link/OTP). |
send_link_sms | boolean | No | Send the signing link by SMS (requires phone). |
send_otp_sms | boolean | No | Require SMS OTP for this recipient (requires phone). |
read_only | boolean | No | Mark the link as view-only (no signing). |
Example JSON Payload
{
"type": "send_link",
"email_template_id": 21,
"documents": [
{
"document_template_id": 125,
"combine": 1,
"merge": {
"first_name": "Joe",
"middle_name": "",
"last_name": "Lowe",
"client_full_name": "Joe Blogs",
"date_of_birth": "1988-04-20",
"current_address": "10 High Street, Leeds, LS1 2AB",
"previous_address": "Flat 2, 14 Old Road, Leeds, LS11 3CD",
"previous_name": "",
"email_address": "joe.blogs@example.com",
"contact_number": "07841939203",
"lender_name": "Example Bank plc",
"registration_number": "AB12 CDE",
"s": "",
"i": "",
"todays_date": "2025-09-04",
"claim_id": "CLM-123456",
"client_id": "C-987654"
},
"recipients": [
{
"recipient_number": 1,
"name": "Joe Blogs",
"email": "joe.blogs@example.com",
"phone": ""
}
]
}
]
}
The fields shown in the example JSON correspond directly to the schema described above. You can replace the user-defined values in the merge object to customize the document for each recipient.
Response
If successful, the response will contain the secure link information and the details of the sent documents:
{
"ok": true,
"envelope_token": "abcdef1234567890",
"links": [
{
"secure_link_id": 1234,
"expires_at": "2025-09-04T15:00:00+00:00",
"status": "sent",
"external_ref": "12345"
}
],
"docs": [
{
"doc_id": 5,
"doc_token": "xyz123",
"name": "Sample Document",
"version": "1.0",
"pages": 3
}
],
"docs_charged": 1,
"spent": "£1.50",
"remaining": "£3.00"
}
Download Signed Document
/api/download_signed
Downloads the signed document by its token and returns the document details along with the base64 content.
Request
Send a POST request with the document token to retrieve the signed document.
Request Body
{
"document_token": "your_document_token"
}
Response
200 OK
{
"ok": true,
"file": {
"filename": "agreement-signed.pdf",
"mime": "application/pdf",
"size": 350170,
"sha256": "2a4bd9a8d0a2b8eda8b076cb1db9e94b777dc6e7c1c653032c70f0568e296165",
"content_base64": "BASE64_ENCODED_CONTENT"
}
}
curl -X POST "https://inkless.co.uk/api/download_signed" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"document_token": "your_document_token"}'
<?php
$payload = ["document_token" => "your_document_token"];
$ch = curl_init("https://inkless.co.uk/api/download_signed");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
$body = @{ document_token = "your_document_token" } | ConvertTo-Json -Depth 10
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/download_signed" -Headers @{ Authorization = "Bearer YOUR_API_TOKEN" } -ContentType "application/json" -Body $body
const res = await fetch("https://inkless.co.uk/api/download_signed", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ document_token: "your_document_token" })
});
const data = await res.json();
console.log(data);
import requests, json
payload = { "document_token": "your_document_token" }
headers = { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }
r = requests.post("https://inkless.co.uk/api/download_signed", headers=headers, json=payload)
print(r.json())
Common Errors
| HTTP | Error | Meaning |
|---|---|---|
| 400 | document_token is required | Provide a valid document_token in the body. |
| 404 | document not found | The requested document could not be found. |
| 500 | server error | Unexpected failure (file I/O, network issues, etc.). |
Download Document Archive
/api/download_archive
Downloads a zip archive containing the documents associated with the document token.
Request
Send a POST request with the document token to retrieve the document archive.
Request Body
{
"document_token": "your_document_token"
}
Response
200 OK
{
"ok": true,
"file": {
"filename": "documents-archive.zip",
"mime": "application/zip",
"size": 1024000,
"sha256": "a1b2c3d4e5f67890abcde1234567890abcdef1234567890abcdef1234567890",
"content_base64": "BASE64_ENCODED_CONTENT"
}
}
curl -sS -X POST "https://inkless.co.uk/api/download_archive" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"document_token": "your_document_token"}'
<?php
$payload = ["document_token" => "your_document_token"];
$ch = curl_init("https://inkless.co.uk/api/download_archive");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
$body = @{ document_token = "your_document_token" } | ConvertTo-Json -Depth 10
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/download_archive" -Headers @{ Authorization = "Bearer YOUR_API_TOKEN" } -ContentType "application/json" -Body $body
const res = await fetch("https://inkless.co.uk/api/download_archive", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ document_token: "your_document_token" })
});
const data = await res.json();
console.log(data);
import requests, json
payload = { "document_token": "your_document_token" }
headers = { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }
r = requests.post("https://inkless.co.uk/api/download_archive", headers=headers, json=payload)
print(r.json())
Common Errors
| HTTP | Error | Meaning |
|---|---|---|
| 400 | document_token is required | Provide a valid document_token in the body. |
| 404 | document not found | The requested document could not be found. |
| 500 | server error | Unexpected failure (archive creation, file I/O, etc.). |
Download Envelope Archive
/api/download_envelope_archive
Downloads a zip archive containing all the documents within an envelope.
Request
Send a POST request with the envelope token to retrieve the envelope archive.
Request Body
{
"envelope_token": "your_envelope_token"
}
Response
200 OK
{
"ok": true,
"file": {
"filename": "envelope-documents-archive.zip",
"mime": "application/zip",
"size": 1536000,
"sha256": "3b6c5d9a3b5c9e89fabae0234567890abcdef1234567890abcdef1234567890",
"content_base64": "BASE64_ENCODED_CONTENT"
}
}
curl -sS -X POST "https://inkless.co.uk/api/download_envelope_archive" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"envelope_token": "your_envelope_token"}'
<?php
$payload = ["envelope_token" => "your_envelope_token"];
$ch = curl_init("https://inkless.co.uk/api/download_envelope_archive");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
$body = @{ envelope_token = "your_envelope_token" } | ConvertTo-Json -Depth 10
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/download_envelope_archive" -Headers @{ Authorization = "Bearer YOUR_API_TOKEN" } -ContentType "application/json" -Body $body
const res = await fetch("https://inkless.co.uk/api/download_envelope_archive", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ envelope_token: "your_envelope_token" })
});
const data = await res.json();
console.log(data);
import requests, json
payload = { "envelope_token": "your_envelope_token" }
headers = { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }
r = requests.post("https://inkless.co.uk/api/download_envelope_archive", headers=headers, json=payload)
print(r.json())
Common Errors
| HTTP | Error | Meaning |
|---|---|---|
| 400 | envelope_token is required | Provide a valid envelope_token in the body. |
| 404 | envelope not found | The requested envelope could not be found. |
| 500 | server error | Unexpected failure (archive creation, file I/O, etc.). |
Get Envelope Status
/api/get_envelope_status
Fetches the status of an envelope to check the signing progress and details of its recipients.
Request
Send a POST request with the envelope token to get the envelope status.
Request Body
{
"envelope_token": "your_envelope_token"
}
Response
200 OK
{
"ok": true,
"status": "in_progress",
"recipients": [
{
"name": "Joe Blogs",
"email": "Joe@example.com",
"status": "signed",
"signed_at": "2025-09-05 10:14:00"
},
{
"name": "Manager",
"email": "manager@example.com",
"status": "pending"
}
]
}
curl -sS -X POST "https://inkless.co.uk/api/get_envelope_status" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"envelope_token": "your_envelope_token"}'
<?php
$payload = ["envelope_token" => "your_envelope_token"];
$ch = curl_init("https://inkless.co.uk/api/get_envelope_status");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_TOKEN", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
$body = @{ envelope_token = "your_envelope_token" } | ConvertTo-Json -Depth 10
Invoke-RestMethod -Method Post -Uri "https://inkless.co.uk/api/get_envelope_status" -Headers @{ Authorization = "Bearer YOUR_API_TOKEN" } -ContentType "application/json" -Body $body
const res = await fetch("https://inkless.co.uk/api/get_envelope_status", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ envelope_token: "your_envelope_token" })
});
const data = await res.json();
console.log(data);
import requests, json
payload = { "envelope_token": "your_envelope_token" }
headers = { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }
r = requests.post("https://inkless.co.uk/api/get_envelope_status", headers=headers, json=payload)
print(r.json())
Common Errors
| HTTP | Error | Meaning |
|---|---|---|
| 400 | envelope_token is required | Provide a valid envelope_token in the body. |
| 404 | envelope not found | The requested envelope could not be found. |
| 500 | server error | Unexpected failure (status retrieval, network issues, etc.). |
Error Handling
We return a non-2xx HTTP status and a JSON body with ok: false and an error key. Your client should check response.ok and handle these values appropriately.
For example:
{
"ok": false,
"error": "documents is required"
}
Common errors
| HTTP | Error | Meaning |
|---|---|---|
| 400 | documents is required | Provide a non-empty documents array with valid document IDs. |
| 400 | document_id is required | Each document must have a valid document_id. It is required for mapping and document preparation. |
| 400 | email_template_id is required | Provide a valid email template ID. |
| 400 | no valid documents or recipients | Check document IDs and recipients (name, email, and recipient numbers). |
| 401 | — | Missing or invalid token. |
| 402 | insufficient_credits | Buy credits or top up. |
| 403 | email template not found for this company | Template ownership mismatch. |
| 403 | invalid_document_ids | One or more documents aren’t owned by your company. |
| 500 | server error | Unexpected failure (conversion, I/O). Retry or contact support. |
Webhooks (optional)
Inkless can POST JSON to your webhook endpoint for events such as:
document_signing_link_sentdocument_signedarchive_readylink_resent
{
"event": "document_signed",
"company_id": 16,
"doc_token": "a1b2...c3d4",
"secure_link_id": 271,
"recipient": { "name": "Joe Blogs", "email": "Joe@example.com" },
"signed_at": "2025-09-04T10:25:31Z",
"metadata": { "ip": "203.0.113.5", "user_agent": "..." }
}
Ask support to enable & configure your webhook URL. Use HTTPS. We can sign payloads and retry deliveries if needed.
Changelog
- 2025-09-04 — Added docs for
get_credits,list_email_templates,list_document_templates, andget_artifact. Kept layout, added PHP/Python examples, generic tab & copy handling. - 2025-09-04 — Initial docs for
send_link. Credits check & debit, ownership checks, audit logging, first-batch mailing.