v1

API Reference

·https://api.docura.cloud/v1

Getting started

Docura API Reference

The Docura REST API lets you create templates, send documents for signing, track status, download signed PDFs, and receive real-time webhook notifications — all programmatically.

The API follows standard REST conventions: JSON request and response bodies, HTTP verbs for actions, and predictable resource URLs. All endpoints return consistent error shapes.

Authentication

All API requests must include a secret API key in the Authorization header. Keys are prefixed dsign_ and scoped to your organisation.

bash
curl https://api.docura.cloud/v1/templates \
  -H "Authorization: Bearer dsign_live_your_api_key"
API keys carry full access to your organisation's data. Never expose them in client-side code or public repositories. Rotate a key immediately if it is compromised via Settings → API Keys.

Keys are created in the dashboard. You can have up to 10 active keys per organisation. Each key can be named and revoked independently.

Quickstart

Send your first document for signing in 3 API calls. First, create a template in the dashboard (drag your PDF fields visually), then use the API to send it.

Step 1 — Get your template ID

bash
curl https://api.docura.cloud/v1/templates \
  -H "Authorization: Bearer dsign_live_..."

# Response → pick a template id from "data"

Step 2 — Create a submission (send for signing)

bash
curl -X POST https://api.docura.cloud/v1/templates/tmpl_01HZ.../submissions \
  -H "Authorization: Bearer dsign_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "signers": [
      {
        "roleId": "role_01HZ...",
        "email": "jane@acme.com",
        "name": "Jane Smith"
      }
    ],
    "signingOrder": "PARALLEL",
    "message": "Please review and sign the attached NDA.",
    "expiresInDays": 7
  }'

Step 3 — Poll for completion or use a webhook

bash
curl https://api.docura.cloud/v1/submissions/sub_01HZ... \
  -H "Authorization: Bearer dsign_live_..."

# When status === "COMPLETED" → download the signed PDF
curl https://api.docura.cloud/v1/submissions/sub_01HZ.../download \
  -H "Authorization: Bearer dsign_live_..." \
  --output signed-document.pdf

Base URL & versioning

text
Base URL:   https://api.docura.cloud/v1
Version:    v1 (current, stable)
Format:     JSON — Content-Type: application/json

The API is versioned by path prefix. Breaking changes will be introduced in a new version (/v2) with a 6-month deprecation window for v1.

Templates

A template is a PDF document with pre-defined field positions and signer roles. Templates are created visually in the dashboard builder and then sent to signers via the submissions endpoint.

Template creation (uploading a PDF) is dashboard-only. The API manages metadata and triggers sending.

GET List templates

GET/v1/templates

Returns a paginated list of active templates for your organisation.

Query parameters

ParameterTypeRequiredDescription
pageintegerNoPage number. Defaults to 1.
limitintegerNoResults per page. 1–100. Defaults to 20.

Response

json
{
  "data": [
    {
      "id": "tmpl_01HZ5X9BKPQR3V2M",
      "name": "Non-Disclosure Agreement",
      "description": "Standard 2-page NDA for contractors",
      "pageCount": 2,
      "signerRoles": [
        { "id": "role_01HZ...", "name": "Client", "order": 1, "color": "#6366f1" },
        { "id": "role_02HZ...", "name": "Vendor", "order": 2, "color": "#f59e0b" }
      ],
      "createdAt": "2026-01-15T09:00:00Z",
      "updatedAt": "2026-03-20T14:30:00Z"
    }
  ],
  "total": 12,
  "page": 1,
  "limit": 20
}

GET Get a template

GET/v1/templates/:id
json
{
  "id": "tmpl_01HZ5X9BKPQR3V2M",
  "name": "Non-Disclosure Agreement",
  "description": "Standard 2-page NDA for contractors",
  "pageCount": 2,
  "signerRoles": [
    { "id": "role_01HZ...", "name": "Client", "order": 1, "color": "#6366f1" }
  ],
  "createdAt": "2026-01-15T09:00:00Z",
  "updatedAt": "2026-03-20T14:30:00Z"
}

PUT Update a template

PUT/v1/templates/:id

Update a template's name or description. All fields are optional.

ParameterTypeRequiredDescription
namestringNoTemplate name. 1–200 characters.
descriptionstringNoOptional description. Max 1,000 characters.
bash
curl -X PUT https://api.docura.cloud/v1/templates/tmpl_01HZ... \
  -H "Authorization: Bearer dsign_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "NDA v2 — Updated" }'

DELETE Delete a template

DELETE/v1/templates/:id

Soft-deletes a template. It will no longer appear in lists or accept new submissions.

json
{ "success": true }

Submissions

A submission is an instance of a template sent to one or more signers. Creating a submission immediately emails all signers (or the first signer if sequential) with a unique signing link.

POST Create a submission

POST/v1/templates/:id/submissions

Sends the template to all specified signers. Each signer must correspond to a signer role defined on the template. Use GET /templates/:id to retrieve role IDs.

Body parameters

ParameterTypeRequiredDescription
signersarrayYesArray of signer objects. At least one required.
signers[].roleIdstringYesThe signer role ID from the template.
signers[].emailstringYesSigner's email address. Invitation sent here.
signers[].namestringNoSigner's display name.
signingOrderenumNo"PARALLEL" (default) or "SEQUENTIAL". Sequential sends one at a time in role order.
messagestringNoCustom message included in the signing invitation email. Max 1,000 characters.
expiresInDaysintegerNoDays until the signing link expires. 1–365.
bash
curl -X POST https://api.docura.cloud/v1/templates/tmpl_01HZ.../submissions \
  -H "Authorization: Bearer dsign_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "signers": [
      {
        "roleId": "role_01HZ5X9BKPQR3V2M",
        "email": "jane@acme.com",
        "name": "Jane Smith"
      }
    ],
    "signingOrder": "PARALLEL",
    "message": "Hi Jane, please sign the attached NDA before our kickoff call.",
    "expiresInDays": 7
  }'

Response — 201 Created

json
{
  "id": "sub_01HZ8P4NKQR2V3M",
  "status": "PENDING",
  "signingOrder": "PARALLEL",
  "signers": [
    {
      "id": "sgn_01HZ...",
      "email": "jane@acme.com",
      "name": "Jane Smith",
      "roleName": "Client",
      "status": "PENDING",
      "signingUrl": "https://app.docura.cloud/sign/tok_eyJh..."
    }
  ],
  "createdAt": "2026-06-24T10:30:00Z"
}
Store the signingUrl if you want to embed signing in your own UI. URLs expire when the submission does.

GET Get a submission

GET/v1/submissions/:id

Returns full submission details including per-signer status. Poll this to track progress.

json
{
  "id": "sub_01HZ8P4NKQR2V3M",
  "status": "COMPLETED",
  "signingOrder": "PARALLEL",
  "template": { "id": "tmpl_01HZ...", "name": "Non-Disclosure Agreement" },
  "message": "Hi Jane, please sign the attached NDA...",
  "expiresAt": "2026-07-01T10:30:00Z",
  "completedAt": "2026-06-24T11:15:00Z",
  "createdAt": "2026-06-24T10:30:00Z",
  "signers": [
    {
      "id": "sgn_01HZ...",
      "email": "jane@acme.com",
      "name": "Jane Smith",
      "roleName": "Client",
      "status": "SIGNED",
      "signedAt": "2026-06-24T11:15:00Z",
      "order": 1
    }
  ]
}

GET Download signed PDF

GET/v1/submissions/:id/download

Returns the finalised, signed PDF as a binary stream. The submission must have status === "COMPLETED".

bash
curl https://api.docura.cloud/v1/submissions/sub_01HZ.../download \
  -H "Authorization: Bearer dsign_live_..." \
  --output signed-nda-jane-smith.pdf
Response Content-Type: application/pdf. A download audit event is recorded on each call.

GET Audit trail

GET/v1/submissions/:id/audit

Returns the full chronological event log for the submission. Use this to prove signing sequence, timestamps, and IP addresses in legal proceedings.

json
{
  "submissionId": "sub_01HZ8P4NKQR2V3M",
  "events": [
    {
      "id": "evt_01HZ...",
      "eventType": "SUBMISSION_CREATED",
      "signerId": null,
      "ipAddress": "203.0.113.1",
      "createdAt": "2026-06-24T10:30:00Z",
      "metadata": {}
    },
    {
      "id": "evt_02HZ...",
      "eventType": "SIGNER_VIEWED",
      "signerId": "sgn_01HZ...",
      "ipAddress": "198.51.100.42",
      "createdAt": "2026-06-24T11:10:00Z",
      "metadata": { "userAgent": "Mozilla/5.0..." }
    },
    {
      "id": "evt_03HZ...",
      "eventType": "SIGNER_SIGNED",
      "signerId": "sgn_01HZ...",
      "ipAddress": "198.51.100.42",
      "createdAt": "2026-06-24T11:15:00Z",
      "metadata": {}
    },
    {
      "id": "evt_04HZ...",
      "eventType": "SUBMISSION_COMPLETED",
      "signerId": null,
      "ipAddress": null,
      "createdAt": "2026-06-24T11:15:01Z",
      "metadata": {}
    }
  ]
}

DELETE Void a submission

DELETE/v1/submissions/:id

Voids an in-progress submission. Signing links are immediately invalidated. Cannot void a submission with status === "COMPLETED" or "VOIDED".

json
{ "success": true }

Webhooks

Webhooks deliver real-time HTTP POST notifications to your server when submission or signer events occur. This is more reliable than polling — configure a webhook once and receive events as they happen.

POST Create a webhook

POST/v1/webhooks
ParameterTypeRequiredDescription
urlstringYesHTTPS URL that will receive POST requests. Must be publicly reachable.
eventsstring[]YesArray of event types to subscribe to. At least one required.
secretstringNoSigning secret for payload verification. Min 8 characters. Auto-generated if omitted.
bash
curl -X POST https://api.docura.cloud/v1/webhooks \
  -H "Authorization: Bearer dsign_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/docura",
    "events": [
      "submission.completed",
      "signer.signed",
      "submission.expired"
    ],
    "secret": "wh_secret_super_secure_value"
  }'
json
{
  "id": "wh_01HZ...",
  "url": "https://your-app.com/webhooks/docura",
  "events": ["submission.completed", "signer.signed", "submission.expired"],
  "secret": "wh_secret_super_secure_value",
  "isActive": true
}

GET List webhooks

GET/v1/webhooks
json
{
  "data": [
    {
      "id": "wh_01HZ...",
      "url": "https://your-app.com/webhooks/docura",
      "events": ["submission.completed", "signer.signed"],
      "isActive": true,
      "createdAt": "2026-06-01T09:00:00Z"
    }
  ]
}

PUT Update a webhook

PUT/v1/webhooks/:id
ParameterTypeRequiredDescription
urlstringNoNew destination URL.
eventsstring[]NoReplace the subscribed event types. Min 1.
isActivebooleanNoEnable or disable the webhook without deleting it.

DELETE Delete a webhook

DELETE/v1/webhooks/:id
json
{ "success": true }

Event types

Subscribe to any combination of the following events:

EventWhen it fires
submission.createdA new submission is created
submission.completedAll signers have signed
submission.expiredThe signing deadline passed
submission.declinedAny signer declined
submission.voidedThe submission was voided via API or dashboard
signer.viewedA signer opened their signing link
signer.signedA signer completed signing
signer.declinedA signer declined to sign

Verifying payloads

Every webhook request includes a X-Docura-Signature header — an HMAC-SHA256 of the raw request body signed with your webhook secret. Verify it to ensure requests are genuinely from Docura.

typescript
import crypto from "crypto";

export function verifyWebhook(
  body: string,          // raw request body as a string
  signature: string,     // X-Docura-Signature header value
  secret: string         // your webhook secret
): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body, "utf8")
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(signature, "hex")
  );
}
json
// Example webhook payload
{
  "event": "submission.completed",
  "timestamp": "2026-06-24T11:15:01Z",
  "data": {
    "submissionId": "sub_01HZ8P4NKQR2V3M",
    "status": "COMPLETED",
    "templateId": "tmpl_01HZ...",
    "completedAt": "2026-06-24T11:15:00Z"
  }
}

Reference

Status enums

Submission status

ParameterTypeRequiredDescription
DRAFTstringNoCreated but not yet sent.
PENDINGstringNoSent. Waiting for all signers.
COMPLETEDstringNoAll signers have signed. PDF available to download.
DECLINEDstringNoOne or more signers declined.
EXPIREDstringNoSigning deadline passed before completion.
VOIDEDstringNoCancelled via API or dashboard.

Signer status

ParameterTypeRequiredDescription
PENDINGstringNoInvitation not yet sent (sequential, waiting for prior signer).
INVITEDstringNoInvitation email sent.
VIEWEDstringNoSigner opened the signing link.
SIGNEDstringNoSigner completed all fields.
DECLINEDstringNoSigner declined to sign.

Error codes

All errors return a consistent JSON shape:

json
{
  "error": {
    "code": "SUBMISSION_ALREADY_COMPLETED",
    "message": "Cannot void a completed submission.",
    "status": 422
  }
}
HTTPCause
400Invalid request body — Zod validation failed. Check the error details.
401Missing or invalid API key.
403The resource exists but belongs to a different organisation.
404Resource not found.
422Business logic error — e.g. voiding a completed submission.
429Rate limit exceeded. See X-RateLimit-Reset header.
500Unexpected server error. Retrying with exponential backoff is safe.

Rate limits

Requests are rate-limited per API key. Response headers indicate your current usage:

text
X-RateLimit-Limit:     1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset:     1719230400   # Unix timestamp
PlanRequests / minuteRequests / day
Free60500
Starter3005,000
Professional60020,000
EnterpriseCustomCustom
When you hit a 429, wait until X-RateLimit-Reset before retrying. Use exponential backoff for reliability.