/documentsUpload a PDF
Multipart form upload, field name `file`. Returns the version id used to create agreements. Scope: write.
Developers
Send PDFs for signature from your own systems, follow progress with signed webhooks, and download the sealed document and its evidence package.
Create a key in Settings → Developers (Business plan). Send it as a bearer token. Keys act with the permissions of the person who created them, limited to their scopes: read and/or write. Keys can never reach account, team, billing or admin routes. Limit: 600 requests per minute per key.
curl https://mydocument.online/api/v1/agreements \ -H "Authorization: Bearer ps_live_xxxxxxxxxx_..."
Every write accepts an Idempotency-Key header. Retries with the same key within 24 hours return the original response (with Idempotent-Replayed: true) instead of sending a document twice. Reusing a key for a different request returns 422.
Errors are JSON with a message, and for validation errors an issues array. A plan limit returns 402 with code: "PLAN_LIMIT".
{ "message": "Validation failed", "issues": [{ "path": "recipients.0.email", "message": "Invalid email" }] }Add endpoints in Settings → Developers. Each event is a JSON POST with PdfSign-Event, PdfSign-Delivery and PdfSign-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 of t.rawBody with your endpoint secret. Respond with any 2xx within 10 seconds. Failures retry with backoff for about a day; you can replay any delivery from the dashboard. Events are delivered at least once: de-duplicate on the event id.
Events: agreement.created, agreement.sent, recipient.viewed, recipient.authenticated, recipient.signed, recipient.declined, agreement.declined, agreement.completed, agreement.expired, agreement.voided, agreement.cancelled.
import crypto from 'node:crypto';
// Express: app.post('/webhooks/pdfsign', express.raw({ type: 'application/json' }), handler)
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300; // reject replays older than 5 minutes
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Upload PDFs
/documentsMultipart form upload, field name `file`. Returns the version id used to create agreements. Scope: write.
Prepare, send and track agreements
/agreementsstatus (query) — Comma-separated statuses, e.g. SENT,COMPLETEDq (query) — Search title, recipient name or emailpage (query) pageSize (query) /agreements| documentVersionId* | string (uuid) | |
| title* | string | |
| message | string | |
| signingOrder | "SEQUENTIAL" | "PARALLEL" | Default "SEQUENTIAL". |
| expiresAt | any | |
| reminderEveryDays | integer | null | |
| reminderMax | integer |
/agreements/{id}id (path) /agreements/{id}id (path) | title | string | |
| message | string | null | |
| signingOrder | "SEQUENTIAL" | "PARALLEL" | |
| expiresAt | any | null | |
| reminderEveryDays | integer | null | |
| reminderMax | integer |
/agreements/{id}/recipientsid (path) | recipients* | object[] |
|
/agreements/{id}/fieldsCoordinates are fractions (0–1) of the page as displayed, origin top-left.
id (path) | fields* | object[] |
|
/agreements/{id}/sendid (path) /agreements/{id}/cancelid (path) | reason | string |
/agreements/{id}/recipients/{recipientId}/remindid (path) recipientId (path) /agreements/{id}/auditid (path) /agreements/{id}/downloadid (path) file (query) /agreements/{id}/evidenceid (path) Reusable documents with roles and fields
/templates/templates/{id}id (path) /templates/{id}/agreementsProvide one person per template role. Set `send: true` to send immediately.
id (path) | title | string | |||||||||||||
| message | string | |||||||||||||
| recipients* | object[] |
| ||||||||||||
| send | boolean | Default false. |