DEVELOPER DOCS

REST API Reference

Programmatically manage documents, envelopes, templates, and webhooks. 25 endpoints to integrate Agreements.ai into your workflow.

Base URL

https://api.agreements.ai

All API paths are relative to this base URL. This is separate from the main website.

Authentication

Create API keys in Settings → Developers tab. Include your key in the Authorization header:

Header
Authorization: Bearer sk_your_api_key_here

Firebase ID tokens are also accepted as Bearer tokens for browser-based integrations.

Rate Limits

  • • Read operations (GET): 30 requests/min
  • • Write operations (POST/PUT/DELETE): 10 requests/min
  • • Remind / Resend: 5 requests/min

Response Formats

Single resource

{ "id": "env_abc123", "status": "pending", ... }

List response

{
  "data": [ ... ],
  "total": 42,
  "limit": 20,
  "offset": 0
}

Error response

{
  "error": "Envelope not found",
  "code": "NOT_FOUND"
}

Endpoints

Envelopes

Create, manage, and track signing envelopes.

GET
/v1/envelopesList envelopes
Query: status, limit, offset
POST
/v1/envelopesCreate & send envelope
GET
/v1/envelopes/:idGet envelope details
DELETE
/v1/envelopes/:idVoid envelope
GET
/v1/envelopes/:id/auditGet audit trail
GET
/v1/envelopes/:id/documentDownload document content
POST
/v1/envelopes/:id/remindSend reminder to pending signers
POST
/v1/envelopes/:id/voidVoid envelope with reason
PUT
/v1/envelopes/:id/recipientsUpdate signers
POST
/v1/envelopes/:id/resendResend signing notification

Documents

Manage your document library.

GET
/v1/documentsList documents
Query: limit, status, search
POST
/v1/documentsCreate document
GET
/v1/documents/:idGet document with content
PUT
/v1/documents/:idUpdate document
DELETE
/v1/documents/:idDelete document

Templates

Browse and use document templates.

GET
/v1/templatesList templates
Query: category, search, limit
GET
/v1/templates/:idGet template details
POST
/v1/templates/:id/useCreate document from template

Webhooks

Manage webhook subscriptions for real-time event notifications.

GET
/v1/webhooksList webhooks
POST
/v1/webhooksCreate webhook
GET
/v1/webhooks/:idGet webhook details
PUT
/v1/webhooks/:idUpdate webhook
DELETE
/v1/webhooks/:idDelete webhook
POST
/v1/webhooks/:id/testSend test event

Account

Retrieve account information and usage.

GET
/v1/accountGet plan, usage, and limits

Code Examples

Create & Send an Envelope

cURL
curl -X POST https://api.agreements.ai/v1/envelopes \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "documentId": "doc_abc123",
    "signers": [
      { "id": "s1", "label": "Client", "name": "John Doe", "email": "[email protected]" }
    ],
    "fields": [
      { "id": "f1", "type": "signature", "signerId": "s1", "label": "Client Signature" }
    ],
    "options": {
      "signingOrder": "parallel",
      "message": "Please review and sign this agreement."
    }
  }'
Node.js
const res = await fetch('https://api.agreements.ai/v1/envelopes', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_your_api_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    documentId: 'doc_abc123',
    signers: [{ id: 's1', label: 'Client', name: 'John Doe', email: '[email protected]' }],
    fields: [{ id: 'f1', type: 'signature', signerId: 's1', label: 'Client Signature' }],
    options: { signingOrder: 'parallel', message: 'Please review and sign.' },
  }),
});
const envelope = await res.json();
console.log(envelope.id);
Python
import requests

resp = requests.post(
    "https://api.agreements.ai/v1/envelopes",
    headers={"Authorization": "Bearer sk_your_api_key"},
    json={
        "documentId": "doc_abc123",
        "signers": [{"id": "s1", "label": "Client", "name": "John Doe", "email": "[email protected]"}],
        "fields": [{"id": "f1", "type": "signature", "signerId": "s1", "label": "Client Signature"}],
        "options": {"signingOrder": "parallel", "message": "Please review and sign."},
    },
)
envelope = resp.json()
print(envelope["id"])

List Documents

cURL
curl "https://api.agreements.ai/v1/documents?limit=10&search=lease" \
  -H "Authorization: Bearer sk_your_api_key"
Node.js
const res = await fetch('https://api.agreements.ai/v1/documents?limit=10&search=lease', {
  headers: { 'Authorization': 'Bearer sk_your_api_key' },
});
const { data, total } = await res.json();
console.log(`Found ${total} documents`);
Python
resp = requests.get(
    "https://api.agreements.ai/v1/documents",
    headers={"Authorization": "Bearer sk_your_api_key"},
    params={"limit": 10, "search": "lease"},
)
result = resp.json()
print(f"Found {result['total']} documents")

Create Document from Template

cURL
curl -X POST https://api.agreements.ai/v1/templates/tpl_nda01/use \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "variables": {
      "company_name": "Acme Inc.",
      "effective_date": "2026-03-01",
      "party_name": "John Doe"
    }
  }'
Node.js
const res = await fetch('https://api.agreements.ai/v1/templates/tpl_nda01/use', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_your_api_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    variables: { company_name: 'Acme Inc.', effective_date: '2026-03-01', party_name: 'John Doe' },
  }),
});
const doc = await res.json();
console.log(doc.id); // newly created document ID
Python
resp = requests.post(
    "https://api.agreements.ai/v1/templates/tpl_nda01/use",
    headers={"Authorization": "Bearer sk_your_api_key"},
    json={"variables": {"company_name": "Acme Inc.", "effective_date": "2026-03-01", "party_name": "John Doe"}},
)
doc = resp.json()
print(doc["id"])

Set Up a Webhook

cURL
curl -X POST https://api.agreements.ai/v1/webhooks \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook",
    "events": ["signing.completed", "signing.declined"],
    "secret": "whsec_your_secret_key"
  }'
Node.js
const res = await fetch('https://api.agreements.ai/v1/webhooks', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_your_api_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://your-server.com/webhook',
    events: ['signing.completed', 'signing.declined'],
    secret: 'whsec_your_secret_key',
  }),
});
const webhook = await res.json();
console.log(webhook.id);
Python
resp = requests.post(
    "https://api.agreements.ai/v1/webhooks",
    headers={"Authorization": "Bearer sk_your_api_key"},
    json={
        "url": "https://your-server.com/webhook",
        "events": ["signing.completed", "signing.declined"],
        "secret": "whsec_your_secret_key",
    },
)
webhook = resp.json()
print(webhook["id"])

Webhook Events Reference

Events you can subscribe to when creating or updating webhooks.

EventDescription
signing.sentTriggered when a document is sent for signing.
signing.completedTriggered when all signers have completed signing.
signing.voidedTriggered when the sender voids a signing request.
signing.declinedTriggered when a signer declines to sign.
signing.openedTriggered when a signer opens the signing link.
signing.reminder_sentTriggered when a reminder email is sent to a signer.

Webhook Payload Format

All webhook payloads follow this structure:

POST https://your-server.com/webhook
{
  "event": "signing.completed",
  "timestamp": "2026-02-10T12:00:00Z",
  "data": {
    "documentId": "abc123",
    "documentTitle": "Employment Agreement",
    "signers": [
      {
        "name": "John Doe",
        "email": "[email protected]",
        "status": "signed",
        "signedAt": "2026-02-10T12:00:00Z"
      }
    ],
    "completedAt": "2026-02-10T12:00:00Z"
  }
}

Headers

Content-Type: application/json
X-Agreements-Event: signing.completed
X-Agreements-Signature: a1b2c3d4...

Verifying Webhook Signatures

Every webhook includes an X-Agreements-Signature header — an HMAC-SHA256 hex digest of the body signed with your secret. Always verify before processing.

Node.js
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
Python
import hmac, hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(signature, expected)

Best Practices

  • Respond quickly. Return a 2xx status within 10 seconds. Process events asynchronously.
  • Verify signatures. Always validate the HMAC signature before processing.
  • Handle duplicates. Use the event timestamp and document ID for idempotency.
  • Use HTTPS only. Webhook URLs must use HTTPS for security.
  • Respect rate limits. Back off on 429 responses. Use exponential retry.

Ready to integrate?

Create your API key and start building in minutes.

Get API Key →

© 2026 Agreements.ai. All rights reserved.