ChaindocLabs

Last updated: April 28, 2026

Chaindoc REST API reference

Full endpoint reference for the Chaindoc REST API. Covers authentication, documents, signatures, media uploads, embedded sessions, and blockchain verification.

API basics

Base URL: https://api.chaindoc.io/api/v1 (Authentication: Bearer token (API key)) Business plan required. If you haven't set up API keys yet, see the API integration guide for setup and common patterns.

Overview

The API gives you programmatic access to everything in Chaindoc: documents, signatures, blockchain verification, and team management. It's designed for server-to-server use and supports both public and secret API keys. Learn more in the RFC 9110 — HTTP Semantics.

  • Documents: create, update, and verify documents on the blockchain
  • Signatures: send signature requests and track completion
  • Media: upload PDFs, images, and videos (max 10 per request)
  • Contracts: draft, send, cancel, and terminate contracts with optional payment terms
  • Invoices & Transactions: bill contragents, charge saved payment methods, track settlements
  • Templates: render documents, signature requests, and contracts from published templates
  • Embedded sessions: create signing sessions for your frontend (uses the Embed SDK)

Authentication

Every request needs an API key in the Authorization header. There are two types:. Learn more in the RFC 6749 — OAuth 2.0.

Key types

  • Public key (pk_). read-only, safe for frontend code
  • Secret key (sk_). full read/write, backend only. Never expose in client-side code.

Key security

Store keys in environment variables, not in your codebase. Rotate keys periodically and immediately after any suspected compromise. See the security guide for more.

Getting your keys

  1. 1
    Subscribe to Business planOnly Business plan users can create API keys
  2. 2
    Navigate to API AccessGo to Settings → API Access in your dashboard
  3. 3
    Create API keyClick Create API Key button
  4. 4
    Store securelyStore the secret key securely (shown only once)

Using API keys

Include your API key in the Authorization header with Bearer authentication:

bash
curl -X GET https://api.chaindoc.io/api/v1/me \
  -H "Authorization: Bearer sk_xxxxxxxxxxxxx"

Rate limiting

All public API endpoints are limited to 10 requests per 60 seconds per API key. When the limit is exceeded, you'll receive a 429 Too Many Requests response. back off and retry after a short delay.

Error handling

HTTP status codes

  • 200 - Success
  • 201 - Resource created successfully
  • 400 - Bad request (validation error)
  • 401 - Unauthorized (invalid or missing API key)
  • 403 - Forbidden (insufficient permissions)
  • 404 - Resource not found
  • 429 - Too many requests (rate limit exceeded)
  • 500 - Internal server error

Error response format

json
{
  "statusCode": 400,
  "message": [
    "name must be a string",
    "recipients should not be empty"
  ],
  "error": "Bad Request"
}

Validation errors return message as an array of human-readable strings, one per failed constraint. For non-validation errors (401, 403, 404, 500), message is a single string.

General API

Get API key info

Get information about the current API key.

GET /me

Authorization: Bearer sk_xxxxx

Health check

Verify API connectivity and key validity.

GET /health

Authorization: Bearer sk_xxxxx

Documents API

Create document

Create a new document with blockchain verification. When status is set to 'published', the document is automatically verified on blockchain.

POST /documents

Headers:
Authorization: Bearer sk_xxxxx
Content-Type: application/json

Update document

Update a document by creating a new version. Previous versions are preserved for audit trail.

PUT /documents/:documentId

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Update document access rights

Update document access control settings.

PUT /documents/:documentId/rights

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Verify document

Verify document authenticity using blockchain. Returns verification status with transaction hash and chain ID.

POST /documents/verify

Authorization: Bearer pk_xxxxx
Content-Type: application/json

{
  "versionHash": "0x123abc...",
  "certificateHash": "0x456def..."
}

Get verification status

Get blockchain verification status for a document version.

GET /documents/versions/:versionId/verification

Authorization: Bearer sk_xxxxx

Signatures API

Create signature request

Create a signature request for one or more recipients. Enable embedded flow for frontend integration.

curl -X POST https://api.chaindoc.io/api/v1/signatures/requests \
  -H "Authorization: Bearer sk_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "versionId": "f0b7721f-0399-4035-9b69-7b95d3a367f0",
    "recipients": [
      { "email": "signer@example.com", "signingMethod": "embedded" }
    ],
    "deadline": "2026-12-31T23:59:59Z",
    "embeddedFlow": true,
    "isKycRequired": false
  }'

Pre-placed fields (advanced). If you upload your own PDF and want exact control over where signature, initials, date, text, or checkbox fields appear, pass an optional fields array alongside versionId. When you render a document from a template (see Templates API below), placed fields come from the template definition automatically. skip this option.

json
{
  "fields": [
    {
      "signerEmail": "signer@example.com",
      "fieldType": "signature",
      "pageIndex": 0,
      "xPct": 0.15,
      "yPct": 0.78,
      "wPct": 0.25,
      "hPct": 0.05,
      "required": true,
      "label": "Client signature"
    },
    {
      "signerEmail": "signer@example.com",
      "fieldType": "date_signed",
      "pageIndex": 0,
      "xPct": 0.45,
      "yPct": 0.78,
      "wPct": 0.15,
      "hPct": 0.03
    }
  ]
}

Placed field conventions

Coordinates are percentages of the page (xPct, yPct, wPct, hPct. all 01), so placements stay correct regardless of PDF page size

pageIndex is zero-based

fieldType accepts signature, initials, date_signed, text, checkbox

signerEmail must match one of the emails in your recipients array

Optional systemKey enables autofill from the signer's profile (e.g. full_name)

Get signature request status

Check the status of a signature request and see which signers have completed signing.

GET /signatures/requests/:requestId/status

Authorization: Bearer sk_xxxxx

Sign document

Sign a document (if API key owner is a signatory).

POST /signatures/sign

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Get user signatures

Get all signatures for the authenticated user.

GET /signatures?pageNumber=1&pageSize=10

Authorization: Bearer sk_xxxxx

Get signature requests

Get all signature requests for the authenticated user with pagination support.

GET /signatures/requests?pageNumber=1&pageSize=10

Authorization: Bearer sk_xxxxx

Media upload API

Upload files for use in document creation. Supports PDF, images, and videos. Maximum 10 files per request.

Supported file types

Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT

Images: JPG, JPEG, PNG, GIF, WEBP, SVG

Videos: MP4, AVI, MOV, WMV

curl -X POST https://api.chaindoc.io/api/v1/media/upload \
  -H "Authorization: Bearer sk_xxxxx" \
  -F "media=@contract.pdf"

Contracts API

Create and manage contract lifecycles from draft through signing, active, and termination. Each contract wraps a document, contragent info, optional payment terms, and a signing policy. Payment-enabled contracts require a Stripe Connect account. see the security guide for setup.

Contract statuses

draft. editable, not yet sent to signers

pending_signature. sent, awaiting signatures from both parties

active. signed by both parties and in effect

pending_amendment. changes proposed, awaiting approval

suspended. temporarily paused

termination_pending. termination requested, awaiting approval (for mutual_approval contracts)

terminated. contract ended by termination

expired. reached endDate without renewal

rejected. declined or cancelled before activation

Create contract

Create a contract in draft status from an existing document. Payment terms are optional. you can add them later via payment setup.

POST /contracts

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Payment term types

one_time. single payment; requires dueDate and amount

recurring. periodic payments; requires frequency (weekly | biweekly | monthly | quarterly | yearly) and dayOfPeriod (1–28)

deposit. upfront payment; typically with dueDate

List contracts

List contracts created via the API, with pagination and optional status/search filters.

GET /contracts?page=1&limit=10&status=active&search=acme

Authorization: Bearer sk_xxxxx

Get contract

Fetch full contract details including payment terms, signing status, and contragent info.

GET /contracts/:contractId

Authorization: Bearer sk_xxxxx

Get contract status

Lightweight endpoint for monitoring contract lifecycle without fetching the full payload. Returns current status, signing progress, and a payment summary.

GET /contracts/:contractId/status

Authorization: Bearer sk_xxxxx

Get contract activities

Paginated activity log (created, sent, signed, amended, terminated, etc.) for audit and webhook reconciliation.

GET /contracts/:contractId/activities?page=1&limit=20

Authorization: Bearer sk_xxxxx

Set up payment terms

Attach or replace payment terms on a draft contract. Useful when you create the contract shell first and configure billing separately.

POST /contracts/:contractId/payment-setup

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Send contract for signing

Transition a draft contract to pending_signature and notify both parties. All body fields are optional.

POST /contracts/:contractId/send

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Cancel contract

Cancel a draft contract (never sent) or a pending_signature contract before anyone signs. Irreversible.

POST /contracts/:contractId/cancel

Authorization: Bearer sk_xxxxx

Terminate contract

Terminate an active contract. For mutual_approval contracts this initiates a termination_pending flow where the other party must confirm; for one_side contracts it terminates immediately.

POST /contracts/:contractId/terminate

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Contract Invoices API

Bill contragents on an active contract. Invoices can be auto-generated from recurring payment terms or created manually for ad-hoc billing. Charging saved payment methods is supported for Stripe-enabled contracts.

Invoice statuses

draft. created but not sent

pending. sent to contragent, payment attempt in progress

unpaid. sent but not yet paid

paid. fully paid

partially_paid. partial payment recorded

overdue. past dueDate and unpaid

cancelled. voided

refunded. paid and later refunded

Create invoice

Create a manual invoice on an active contract. Set sendImmediately: true to dispatch to the contragent right away, and autoCharge: true to charge their saved payment method when sent.

POST /contracts/:contractId/invoices

Authorization: Bearer sk_xxxxx
Content-Type: application/json

List contract invoices

List all invoices for a contract with pagination and optional status filter.

GET /contracts/:contractId/invoices?page=1&limit=10&status=unpaid

Authorization: Bearer sk_xxxxx

Get invoice

Fetch full invoice details including line items, transactions, and Stripe checkout URL if applicable.

GET /contracts/:contractId/invoices/:invoiceUuid

Authorization: Bearer sk_xxxxx

Send invoice

Send a draft invoice to the contragent. Set autoCharge: true to attempt immediate charge of a saved payment method.

POST /contracts/:contractId/invoices/:invoiceUuid/send

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Charge invoice

Charge an already-sent invoice using the contragent's saved payment method. Used to retry failed payments or charge on demand.

POST /contracts/:contractId/invoices/:invoiceUuid/charge

Authorization: Bearer sk_xxxxx

Mark invoice as paid

Record an offline/external settlement. wire transfer, cash, or payment through another rail. A manual transaction is recorded for audit.

POST /contracts/:contractId/invoices/:invoiceUuid/mark-paid

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Transactions API

Read payment transactions linked to contract invoices. Transactions capture every charge attempt (successful, failed, or pending) along with Stripe fee breakdown, net amount, and retry history.

Transaction statuses

INITIALISED. created in the system, payment not yet attempted

PENDING. payment in flight (Stripe processing)

SUCCESS. payment captured

FAILED. payment attempt failed; see failureReason

CANCELLED. transaction voided before capture

List contract transactions

List all transactions for a contract across its invoices.

GET /contracts/:contractId/transactions

Authorization: Bearer sk_xxxxx

Get transaction

Fetch a single transaction by UUID with full details: amounts, fees, receipt URL, and retry metadata.

GET /transactions/:transactionUuid

Authorization: Bearer sk_xxxxx

Templates API

Render a published template into a draft document, a signature request, or a contract. passing variable values and slot assignments. The template system supports per-signer variables and role-based slot assignment for contract templates.

Create document from template

Render a template with variables and create a new draft document. Slot assignments aren't needed here. this endpoint only produces the document shell.

POST /templates/:templateId/documents

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Create signature request from template

Render a template, create the document, and immediately send it for signing. Each slotAssignment binds a template signer key to a real recipient email.

POST /templates/:templateId/signature-requests

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Create contract from template

Render a contract template with variables and contragent info, creating a contract and sending it for signing in one call. Slot assignments bind template signer keys to roles (business | contragent). emails are taken from API key owner (for business) and contragent.email.

POST /templates/:templateId/contracts

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Embedded sessions API

Create embedded sessions for document or contract signing in your frontend application. Sessions are valid for 10 minutes. For standalone document signing, pass both documentId and signatureRequestId in metadata. For contract signing, pass contractId and Chaindoc resolves the active signing request.

POST /embedded/sessions

Authorization: Bearer sk_xxxxx
Content-Type: application/json

Embedded session flow

1. Create an embedded session via the API. an OTP is sent to the signer's email

2. The signer verifies the OTP and signs from an iframe on your site

3. The flow is driven by the Embed SDK; the session-scoped endpoints it calls are not part of the public integration surface

4. Your backend is notified of completion via webhooks

What to do next

  • API integration. common patterns, best practices, and full workflow examples
  • SDKs. Server SDK and Embed SDK with framework-specific guides
  • Webhooks. set up real-time event notifications
  • Installation. npm setup for all supported frameworks
  • Security. API key management and compliance