Scribe

Developers

API reference

Send documents for signature and react to signing events programmatically. The API is available on the Business plan.

Authentication

Authenticate every request with an API key as a Bearer token. Create keys in your account under API keys — the plaintext is shown once. Keep it secret; anyone with a key can act on your account.

API access requires the Business plan. Requests without a valid key return 401; keys on non-eligible plans can't be created.

Manage API keys →

Create & send a document

POST /api/v1/documents

One call uploads the PDF, creates the document, and sends invitations. multipart/form-data with a file and a JSON payload. Honors your monthly quota (402 if exhausted).

curl -X POST https://bascribe.com/api/v1/documents \
  -H "Authorization: Bearer bsk_live_..." \
  -F file=@contract.pdf \
  -F 'payload={
    "title": "Service agreement",
    "signingMode": "PARALLEL",
    "signers": [
      { "name": "Ada Lovelace", "email": "ada@example.com", "role": "Client" }
    ]
  }'

# 201 Created
{ "id": "clx…", "status": "SENT", "invited": 1,
  "signers": [ { "name": "Ada Lovelace", "email": "ada@example.com", "status": "PENDING" } ] }

Get document status

GET /api/v1/documents/:id

Poll a document's status and per-signer progress. Prefer webhooks over polling where possible.

curl https://bascribe.com/api/v1/documents/clx… \
  -H "Authorization: Bearer bsk_live_..."

# 200 OK
{ "id": "clx…", "status": "PARTIALLY_SIGNED",
  "signers": [ { "email": "ada@example.com", "status": "SIGNED", "signedAt": "…" } ],
  "executedAvailable": false }

Download the executed PDF

GET /api/v1/documents/:id/executed

Once every signer has signed and the document is finalized, download the executed PDF (signatures + Certificate of Completion). Returns 409 until it's ready.

curl -L https://bascribe.com/api/v1/documents/clx…/executed \
  -H "Authorization: Bearer bsk_live_..." \
  -o executed.pdf   # 409 until COMPLETED

Webhooks

Register HTTPS endpoints under Webhooks to receive events in real time. Each delivery is a POST with a JSON body and is retried on failure (1m, 5m, 30m, 2h, 6h, 24h).

Subscribable events:

document.sentsigner.signedsigner.declineddocument.completed

Verifying signatures

Every delivery carries an X-BAScribe-Signature header: t=<unix>,v1=<hmac>. Recompute the HMAC-SHA256 of "<t>.<rawBody>" with your endpoint secret and compare. Reject timestamps older than 5 minutes.

import { createHmac } from "node:crypto";

function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map(p => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
  return expected === v1;
}