Repository navigation
Webhooks and REST API Integration
The document API lets another application read or change documents. A webhook sends an HTTP callback to your receiver when an event is processed. Subscription setup and actual background delivery are separate concerns.
- Open
/settings/integrations→ Webhooks. - Create a subscription with a clear name and a public HTTPS receiver URL.
- Select only the events your receiver needs.
- Add filters or select payload fields if needed, using the event catalog to check field names.
- Save the subscription and store its one-time signing secret in an approved secret manager.
- Use the test action and inspect the result.
- Test an actual domain event and confirm delivery with the operator.
The inspected Worker entry point does not wire the outbox dispatch and retry services to automatic background processing. A successful synthetic test does not prove real events will be delivered automatically. Ask your operator to confirm those processors before relying on callbacks.
Prefix these paths with /api/v1/webhooks:
| Method | Suffix | Scope | Purpose |
|---|---|---|---|
| GET | /events |
Public catalog | Event definitions, sample data, and supported fields |
| GET |
/, /{id}
|
webhooks:read |
List / retrieve subscriptions |
| POST | / |
webhooks:manage |
Create a subscription; secret returned once |
| PATCH | /{id} |
webhooks:manage |
Update configuration or active/disabled state |
| DELETE | /{id} |
webhooks:manage |
Soft-delete a subscription |
| POST | /{id}/rotate-secret |
webhooks:manage |
New secret, with a 24-hour previous-key grace window |
| POST | /{id}/test |
webhooks:manage |
Synthetic delivery with optional eventType, dataOverrides
|
| GET | /{id}/metrics |
webhooks:read |
Summary and stored buckets; format=csv export |
| GET | /{id}/dead-letters |
webhooks:read |
Terminal failed deliveries |
| POST | /deliveries/{id}/replay |
webhooks:replay |
Create and attempt another delivery generation |
Creation input:
{
"name": "Example document callback",
"targetUrl": "https://receiver.example.com/graphsign",
"eventTypes": ["document.created", "document.updated"],
"filterRules": {"and":[{"field":"data.folder","op":"eq","value":"Examples"}]},
"payloadProjection": {"mode":"CUSTOM","includeFields":["document_id","document_name","status","folder"]},
"rateLimitPerMinute": 10
}name is required (1–255 characters), targetUrl is required (up to 1,024 characters), and at least one event is required. Optional properties include description (500 characters), custom headers, filters, and projection. Rate configuration accepts 1–1,000 with default 10, but current delivery code does not enforce that throttle. Protect your receiver independently.
Use public HTTPS targets for production. Do not configure private infrastructure or place credentials in the target URL. Keep custom header secrets private. The application protects its signature and delivery headers against custom-header replacement.
The registry includes document.created, document.updated, document.deleted, document.sent, document.viewed, document.signed, document.completed, document.declined, document.voided, document.expired, document.verified, user.created, user.updated, user.role_changed, and user.removed.
The event catalog is a schema registry, not a guarantee that every application operation emits every event. Confirm your actual producer path and deployed processing. A wildcard * is accepted, but explicit events reduce unwanted traffic and data disclosure.
Filters support and/or groups and predicates with field, op, and optional value. Operators include eq, neq, in, nin, contains, and exists; nested filters are depth-limited. CUSTOM projection selects event data fields; the standard envelope is still included by fan-out.
Normal callbacks contain id, event, schemaVersion, timestamp, organisationId, sequence, test, and data. Header names are case-insensitive:
| Header | Meaning |
|---|---|
X-Signature |
sha256= followed by the lowercase HMAC-SHA256 hex signature |
X-Signature-Key-ID |
Signing key identifier used to select the stored secret |
X-Event-ID |
Stable event identity |
X-Delivery-ID |
Particular delivery identity |
X-Attempt-Number |
Attempt number for this delivery |
Compute HMAC-SHA256 over the exact raw request body bytes, using the secret's literal UTF-8 text as the key. Do not hex-decode the secret and do not parse/re-serialize the body before checking it. Compare signatures in constant time. Reject missing or invalid signatures.
This Node.js helper illustrates the comparison only; your HTTP framework must pass the unmodified raw body and headers. Store secrets outside source code.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(rawBody, signatureHeader, secret) {
if (!Buffer.isBuffer(rawBody) || typeof signatureHeader !== 'string') return false;
if (!/^sha256=[0-9a-f]{64}$/.test(signatureHeader)) return false;
const expected = createHmac('sha256', secret).update(rawBody).digest();
const received = Buffer.from(signatureHeader.slice(7), 'hex');
return received.length === expected.length && timingSafeEqual(received, expected);
}After verification, validate the event schema, expected organization, and supported event type. Deduplicate by event ID using durable storage before applying business effects. Handle test: true without changing production records. An HMAC alone does not prevent replay, and callbacks should not be treated as ordered or exactly-once.
Return a 2xx response after durably accepting the event. Avoid a slow synchronous workflow in the receiver. Keep previous and new secrets available during the documented rotation window, selecting by key ID.
The delivery service treats 2xx as success and schedules eligible retries with backoff, up to four total attempts. Background execution requires a processor. Terminal failures enter the dead-letter queue. Fix the receiver or configuration before replaying, and ensure replay cannot duplicate a business action.
Metrics summarize stored buckets; the current period parameter is echoed but does not filter those buckets. Do not interpret it as a guaranteed time-window query.
Bindings use /api/v1/organisations/me/api-clients with api_clients:manage:
- GET lists bindings.
- POST registers required
name,clientId, and nonemptyscopes; optional description, issuer, andactingUserIdare supported. - PATCH
/{id}updates name, description, scopes, or status (active,disabled,revoked). - DELETE
/{id}revokes and soft-deletes the binding.
Registration does not issue an OAuth token or client secret. No corresponding client-secret rotation or client-credentials token endpoint is implemented here. Get approved token provisioning instructions from the operator.
GET /api/v1/organisations/me/api-logs requires api_logs:read and supports page/limit plus route, method, statusCode, requestId, from, and to. Use request IDs for private troubleshooting; review exports before sharing.
Next: API Quick Start · REST API Reference · Feature Availability.
Documentation home · Getting started · Troubleshooting · Feature availability
Reviewed 3 October 2026.
graphsign.ink
Using the application
Account and administration
Developer documentation
- API quick start
- REST API reference
- Agreement and workflow API
- Template API
- Account and organization API
- Search API
- Certificates and signing API
- Webhooks and integrations
- Feature availability
Help