Guide

API reference

All paths below are relative to your API's base URL — the hosted default, or your own instance if you're self-hosting (see Self-hosted backend).

Keys are passed as Authorization: Bearer pk_live_... — the header the official SDK's API client sends; mirror it from your own code. Response shapes marked illustrative further down aren't defined in the spec yet — confirm those against a running API. Everything else — the endpoint list, auth requirements, and the SignatureRecord shape — comes directly from the confirmed spec.

Authentication

GET/auth/oauth/github

Start the GitHub OAuth flow.

Auth:

GET/auth/oauth/google

Start the Google OAuth flow.

Auth:

Projects & keys

POST/projects

Create a new project. Returns its key pair — the secret key is only ever shown once.

Auth: Session (dashboard cookie)

Response (illustrative — confirm against real API)

{
  "id": "proj_...",
  "name": "My project",
  "publicKey": "pk_live_...",
  "secretKey": "sk_live_...",
  "createdAt": "2026-07-18T09:12:00Z"
}
POST/projects/:id/keys/rotate

Rotate a project's key pair. The old pair stops working immediately — no overlap window.

Auth: Session (dashboard cookie)

Response (illustrative — confirm against real API)

{
  "publicKey": "pk_live_...",
  "secretKey": "sk_live_..."
}

Signatures

POST/signatures

Submit a captured signature and its metadata.

Auth: Public key (pk_live_ / pk_test_)

Request body

{
  "signature": "M10 10 L90 90 ...",
  "location": null,
  "deviceData": {
    "userAgent": "...",
    "inputType": "touch",
    "pressureSupported": true
  },
  "siteUrl": "https://example.com/agreement",
  "pageName": "agreement",
  "createdBy": "signer@example.com"
}

Response

{
  "id": "sig_...",
  "date": "2026-07-18T09:14:22Z",
  "projectId": "proj_...",
  "signature": "M10 10 L90 90 ...",
  "location": null,
  "deviceData": { "userAgent": "...", "inputType": "touch", "pressureSupported": true },
  "siteUrl": "https://example.com/agreement",
  "pageName": "agreement",
  "createdBy": "signer@example.com"
}
GET/signatures/:id

Retrieve a single signature record by ID.

Auth: Secret key (sk_live_ / sk_test_)

Response

/* full SignatureRecord — see Data model below */
GET/signatures?projectId=

List signatures for a project, paginated.

Auth: Secret key (sk_live_ / sk_test_)

Response (illustrative — confirm against real API)

{
  "data": [ /* SignatureRecord[] */ ],
  "nextCursor": "..."
}
DELETE/signatures/:id

Permanently delete a record — used for right-to-erasure requests.

Auth: Secret key (sk_live_ / sk_test_)

Response (illustrative — confirm against real API)

{ "deleted": true }

Data model: SignatureRecord

The confirmed shape from the technical spec — server-assigned fields are never accepted from the client on write.

interface SignatureRecord {
  id: string;                // UUID, server-assigned
  signature: string;         // SVG path data or base64 PNG
  date: string;               // ISO 8601, server-assigned — not client-trusted
  location?: {
    lat: number;
    lng: number;
    accuracy?: number;
  } | null;                  // null unless the signer opts in
  deviceData: {
    userAgent: string;
    inputType: 'touch' | 'pen' | 'mouse';
    pressureSupported: boolean;
  };
  siteUrl: string;
  pageName: string;
  projectId: string;          // inferred from the public key, not client-supplied
  createdBy: string;          // account email
}

Errors

Standard HTTP status codes apply (400 for malformed requests, 401/403 for auth failures, 404 for missing records). The exact error body shape isn't finalized in the spec yet — check the real response once the API is running rather than relying on this page for it.