Core Concepts
Core concepts of the eContract API, from workspaces and roles to the contract lifecycle, async document processing, signers, signing order and templates.
Understanding these core concepts will help you build effective integrations with the eContract API.
Workspaces
Workspaces are the top-level organizational unit in eContract. Each workspace is an isolated tenant with its own contracts, users, templates, and API keys.
- A user can belong to multiple workspaces
- API keys are scoped to a single workspace
- All API requests operate within the context of one workspace
Workspace Roles
| Role | Description |
|---|---|
owner, admin | Full workspace management: users, API keys, webhooks, settings |
contract_manager | Create, send, and manage contracts |
member | Work with contracts as the workspace allows |
viewer | Read-only access to contracts |
API keys and OAuth tokens act with their user's role capped at contract_manager; see Machine role.
Contract Lifecycle
Contracts follow a defined lifecycle from creation to completion:
┌───────┐ ┌─────────┐ ┌────────────┐ ┌───────────┐
│ DRAFT │────→│ PENDING │────→│ IN_SIGNING │────→│ COMPLETED │
└───────┘ └─────────┘ └────────────┘ └───────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌─────────┐
│ VOIDED │ │ VOIDED │ │ EXPIRED │
└────────┘ └────────┘ └─────────┘Contract Statuses
| Status | Description |
|---|---|
draft | Contract created, can add files and edit details |
pending | Ready but not yet submitted for signing |
in_signing | Sent to signers, awaiting signatures |
completed | All signers have signed |
voided | Cancelled by the creator |
expired | Signing deadline passed (default: 90 days) |
Key Rules
- Only
draftcontracts can be edited, have files added, or be deleted - Contracts in
draftorpendingstatus can be submitted for signing - Contracts can be voided unless they are
completedor alreadyvoided - A contract moves to
completedautomatically when all signers finish
Creating a Contract
curl -X POST https://api.econtract.online/api/v1/contracts \
-H "Authorization: Bearer cl_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"title": "NDA Agreement",
"description": "Mutual non-disclosure agreement",
"signingOrderType": "parallel",
"expiresInDays": 30
}'const contract = await fetch(
"https://api.econtract.online/api/v1/contracts",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ECONTRACT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "NDA Agreement",
description: "Mutual non-disclosure agreement",
signingOrderType: "parallel",
expiresInDays: 30,
}),
}
).then((r) => r.json());contract = requests.post(
"https://api.econtract.online/api/v1/contracts",
headers={"Authorization": f"Bearer {os.environ['ECONTRACT_API_KEY']}"},
json={
"title": "NDA Agreement",
"description": "Mutual non-disclosure agreement",
"signingOrderType": "parallel",
"expiresInDays": 30,
},
).json()Async Contract Processing
The POST /contracts/send endpoint creates and sends a contract in a single API call. Because this involves file processing, signer validation, and contract submission, it runs asynchronously.
How It Works
- Request — You call
POST /contracts/sendwith files/template, signers, and contract details - Immediate response — The API returns
202 Acceptedwith the contract inprocessingstate - Background processing — A worker adds signers, submits the contract, and transitions it to
in_signing - Completion —
processingStatuschanges toready(success) orfailed(error)
Processing Status
| Status | Description |
|---|---|
processing | Background worker is processing the contract |
ready | Processing complete — contract is now in_signing |
failed | An error occurred — check processingError for details |
Monitoring Processing
Option 1: Polling
# Poll GET /contracts/:id until processingStatus changes
curl https://api.econtract.online/api/v1/contracts/{contractId} \
-H "Authorization: Bearer cl_live_your_key"Option 2: Webhooks (recommended)
Register a webhook for these events:
| Event | Description |
|---|---|
contract.processing.completed | Processing succeeded, contract is in_signing |
contract.processing.failed | Processing failed with error |
See Webhooks for setup instructions.
Failure Handling
Processing is retried automatically (up to 3 attempts). When it still fails:
processingStatusis set tofailedprocessingErrorcontains the error message- The contract is kept, so polling clients see the failure instead of a
404 - A
contract.processing.failedwebhook is sent
Fix the input and make a new POST /contracts/send request (with a new Idempotency-Key).
Documents & Files
Each contract can have one or more attached files. Supported formats:
| Format | Notes |
|---|---|
| Native support, no conversion needed | |
| DOCX | Automatically converted to PDF after upload |
Uploading Files
Upload files to a draft contract:
curl -X POST \
"https://api.econtract.online/api/v1/contracts/{contractId}/files" \
-H "Authorization: Bearer cl_live_your_key" \
-F "[email protected]"DOCX Conversion
When you upload a DOCX file, eContract converts it to PDF automatically. The file object includes a conversionStatus field:
| Status | Description |
|---|---|
pending | Conversion queued |
completed | PDF ready |
failed | Conversion error — retry with POST /contracts/{id}/files/{fileId}/retry-conversion |
File Size Limits
- Direct upload: 50 MB per file
- Multipart upload: Use the multipart API for larger files
Signers & Signing Flow
Signers are the people who need to sign a contract. eContract supports both internal users (workspace members) and external signers (anyone with an email address).
Adding Signers to a Draft
POST /contracts/send adds the signers for you. For a draft created with POST /contracts, add them one by one:
curl -X POST "https://api.econtract.online/api/v1/contracts/$CONTRACT_ID/signers" \
-H "Authorization: Bearer cl_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"signerType": "external",
"email": "[email protected]",
"name": "Jane Smith",
"signOrder": 1
}'await fetch(`https://api.econtract.online/api/v1/contracts/${contractId}/signers`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ECONTRACT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
signerType: "external",
email: "[email protected]",
name: "Jane Smith",
signOrder: 1,
}),
});requests.post(
f"https://api.econtract.online/api/v1/contracts/{contract_id}/signers",
headers={"Authorization": f"Bearer {os.environ['ECONTRACT_API_KEY']}"},
json={
"signerType": "external",
"email": "[email protected]",
"name": "Jane Smith",
"signOrder": 1,
},
)/external-signers is the workspace address book of external signers, not the list of a contract's signers.
Signer Statuses
| Status | Description |
|---|---|
pending | Added to contract, not yet notified |
notified | Signing invitation email sent |
viewed | Signer opened the signing page |
signed | Signer completed their signature |
rejected | Signer declined to sign |
expired | Signing period expired |
Signing Order
eContract supports two signing order types:
sequential— Signers are notified one at a time insignOrder. Signer 2 is notified only after Signer 1 completes.parallel— All signers are notified immediately and can sign in any order.
Signing Flow
When a contract is submitted:
- Notification — Signers receive an email with a secure signing link
- View — Signer opens the link and reviews the document
- OTP verification — Signer verifies their identity via email OTP
- Sign or decline — Signer draws/uploads their signature or declines
- Completion — When all signers finish, the contract moves to
completed
Resending Notifications
If a signer hasn't responded, resend the signing request:
curl -X POST \
"https://api.econtract.online/api/v1/contracts/{contractId}/resend-signing-request" \
-H "Authorization: Bearer cl_live_your_key"Templates
Templates let you create reusable contract structures with variable placeholders.
Creating a Template
curl -X POST https://api.econtract.online/api/v1/contract-templates \
-H "Authorization: Bearer cl_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Standard NDA",
"description": "Mutual non-disclosure agreement template",
"category": "legal"
}'Template Variables
Extract variables from a template document:
curl -X POST \
"https://api.econtract.online/api/v1/contract-templates/{templateId}/extract-variables" \
-H "Authorization: Bearer cl_live_your_key"Generating a Contract from a Template
curl -X POST \
"https://api.econtract.online/api/v1/contract-templates/{templateId}/generate" \
-H "Authorization: Bearer cl_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"variables": {
"companyName": "Acme Corp",
"effectiveDate": "2026-04-01"
}
}'This creates a new contract in draft status with the template variables filled in.