Legally binding e-signature API Signing, as an
API call
Create documents from templates, add recipients, and receive HMAC-signed webhooks when signatures land. Every completed document comes back with its audit trail and, on Business and above, a hash anchored on Hedera.
Base URL https://developer.ledgersign.io/api/v1. API access is included from the Business plan.
$ curl -X POST https://developer.ledgersign.io/api/v1/documents \
-H "Authorization: Bearer $LEDGERSIGN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "3f6c1e2a-…",
"title": "Master Services Agreement",
"recipients": [
{ "email": "counsel@client.com", "order": 1 },
{ "email": "cfo@client.com", "order": 2 }
]
}'
201 Created
{
"status": "success",
"message": "Document created",
"data": {
"id": "8c3df21a-…",
"status": "sent",
"recipients": 2
},
"meta": null
}How do I authenticate?
Generate an API key in the dashboard under Settings, then send it as a Bearer token on every request. Keys belong to one organization and inherit that organization's plan, so a Business key gets Business limits.
- Header: Authorization: Bearer <your key>
- One organization per key; documents are scoped to it
- Keys can be revoked from the dashboard at any time
- Keep keys server-side; never ship one in a browser or mobile app
$ curl https://developer.ledgersign.io/api/v1/account/usage \
-H "Authorization: Bearer $LEDGERSIGN_API_KEY"
200 OK
{
"status": "success",
"message": "Usage retrieved",
"data": {
"plan": "business",
"documents_used": 212,
"documents_limit": 500,
"api_calls_used": 1840,
"api_calls_limit": 10000
},
"meta": null
}What does every response look like?
One envelope for every endpoint, so client code handles success and failure the same way everywhere.
{
"status": "error",
"message": "Validation failed",
"errors": {
"recipients": ["At least one recipient is required"]
}
}Success responses carry status, message, data, and meta. Error responses drop data and meta and add errors.
| Status | Meaning |
|---|---|
| 200 / 201 | Success. The envelope carries data and, for lists, meta. |
| 400 | Validation failed. errors lists each field and what was wrong. |
| 401 | No API key, or the key is invalid or revoked. |
| 403 | The key is valid but the plan or the key permissions do not allow this call. |
| 404 | The document, template, or webhook does not exist in your organization. |
| 429 | Rate limit exceeded for the current one-minute window. Back off and retry. |
What are the rate limits?
Limits apply per organization over a one-minute window. Exceed them and the API answers 429 until the window resets.
Business
- Requests per minute
- 300
- API calls per month
- 10,000
- Webhook endpoints
- 5 endpoints
Pro
- Requests per minute
- 1,000
- API calls per month
- 200,000
- Webhook endpoints
- Unlimited
Enterprise
- Requests per minute
- Unlimited
- API calls per month
- Unlimited
- Webhook endpoints
- Unlimited
How does pagination work?
List endpoints take limit (1 to 100, default 20) and offset (default 0), ordered newest first. The meta object echoes both so a client can page without keeping state of its own.
- Filter documents by status (draft, sent, completed, and so on)
- archived=false hides archived documents; archived=true shows only those
- Templates list the same way, with the same limit and offset
$ curl "https://developer.ledgersign.io/api/v1/documents?status=completed&limit=20&offset=40" \
-H "Authorization: Bearer $LEDGERSIGN_API_KEY"
200 OK
{
"status": "success",
"message": "Documents retrieved",
"data": [ { "id": "…", "status": "completed", "sha256": "7f3a92c1…" }, … ],
"meta": { "limit": 20, "offset": 40 }
}How do webhooks work?
Register an endpoint and LedgerSign delivers signing events as they happen. Every payload is signed with HMAC-SHA256 using your endpoint's secret, so you can confirm it came from us before you act on it. The signature covers the raw request body.
Headers on every delivery
- X-Webhook-Signature: hex HMAC-SHA256 of the body
- X-Webhook-Timestamp: when the delivery was sent
- X-Webhook-Event: the event name
Events
document.createddocument.sentdocument.vieweddocument.signeddocument.completeddocument.expiredrecipient.viewedrecipient.signedrecipient.declined
A voided document does not fire a webhook; poll GET /documents/{id} or read the audit trail for that state.
POST /webhooks/ledgersign HTTP/1.1
Content-Type: application/json
X-Webhook-Event: document.completed
X-Webhook-Timestamp: 2026-09-13T14:02:11Z
X-Webhook-Signature: 9f2c41ab…
{
"event": "document.completed",
"created_at": "2026-09-13T14:02:11Z",
"data": {
"document_id": "8c3df21a-…",
"status": "completed",
"sha256": "7f3a92c1…de10e04d",
"blockchain_transaction_id": "0.0.481…@1757…"
}
}Which endpoints exist?
Every route under /api/v1. Request and response schemas are in the OpenAPI reference.
Documents
| Method | Path | Purpose |
|---|---|---|
| POST | /documents | Create and send a document from a template |
| POST | /documents/multi-template | Merge several templates into one envelope, in order |
| POST | /documents/from-file | Upload a PDF and place fields yourself |
| GET | /documents | List documents with status, archived, limit, and offset filters |
| GET | /documents/{id} | Document detail, recipients, and signing status |
| POST | /documents/{id}/void | Void an in-progress document and notify every reached recipient |
| GET | /documents/{id}/download | The signed PDF (and certificate when complete) |
| POST | /documents/{id}/remind | Send a reminder to recipients who have not signed |
| GET | /documents/{id}/audit-trail | Every event with actor, timestamp, IP address, and user agent |
| POST | /documents/{id}/archive | Archive or unarchive (see /unarchive) |
| PATCH | /documents/{id}/signers/{signerId} | Update a signer before they sign |
| POST | /documents/{id}/signers/{signerId}/resend | Re-issue a signing link |
Templates
| Method | Path | Purpose |
|---|---|---|
| GET | /templates | List templates |
| GET | /templates/{id} | Template detail, roles, and fields |
| POST | /templates/{id}/archive | Archive or unarchive (see /unarchive) |
Webhooks and account
| Method | Path | Purpose |
|---|---|---|
| GET / POST | /webhooks | List or register webhook endpoints |
| GET / PATCH / DELETE | /webhooks/{id} | Inspect, update, or remove an endpoint |
| GET | /account/usage | Current usage against plan limits |
| GET | /status | API status for the authenticated organization |
Full schemas: Swagger UI or ReDoc. Verifying an anchored document needs no API at all; see the verification guide.
Send at volume, test without a key
Bulk send via CSV
Upload a CSV and send one template to up to 1,000 recipients in a single batch. Each recipient gets their own document and audit trail, and each completion fires its own webhook.
See how HR teams use itLive API playground
Explore every endpoint, see real request and response shapes, and copy working curl commands before you generate a key.
Open the playgroundShip signing
this sprint
Start on the free plan to model your templates, then move to Business for API keys, webhooks, and anchoring.
API access from $149/month · 300 requests per minute on Business · HMAC-signed webhooks
Page updated September 29, 2026