API overview

REST API for creating, sending, and managing Pacta documents programmatically. Authentication, base URL, OpenAPI spec, and the patterns you need to know.

Last updated May 12, 2026

Pacta’s REST API lets you integrate document signing into your product: create documents, place fields, add recipients, send for signature, and listen for status changes via webhooks — all without anyone touching the Pacta UI.

This article covers the basics. For the full endpoint reference, see the OpenAPI spec.

Base URL

https://sign.pacta.ink/api/v1

The API is hosted under your Pacta production domain. There’s no separate api subdomain. If you self-host Pacta, your base URL is your instance URL

  • /api/v1.

Authentication

Every request authenticates with an API token in the Authorization header:

curl https://sign.pacta.ink/api/v1/documents \
  -H "Authorization: api_..."

Note: no Bearer prefix — the token goes directly in the header value.

Where to get a token

API tokens are per-team, not per-user:

  1. In Pacta → switch to the team you want to issue documents from
  2. Team Settings → API Tokens → + New token
  3. Name the token (e.g., “Production server”, “Staging webhooks”)
  4. Pick expiration (never, 7 days, 30 days, 90 days, 1 year)
  5. Copy the generated token (api_...) — shown once, can’t be retrieved later

The token is scoped to the team that issued it. Any document created via the API is owned by that team. To send documents from multiple teams, generate a separate token per team.

Available scopes

Tokens have full team-level access — they can create, read, update, and delete documents within the team. There’s no per-endpoint scope system today. Treat tokens like service-account credentials: store in a secret manager, rotate when staff leaves, scope to one application per token so you can revoke without affecting others.

OpenAPI spec

The full API reference is auto-generated from the source code and served at:

https://sign.pacta.ink/api/v1/openapi

Tools that consume the spec:

  • Swagger Editor — paste the spec URL
  • Postman → Import → Link → paste the URL → get a fully-populated collection
  • openapi-typescript — generate strict TypeScript types from the spec for your client code
  • Most OpenAPI codegen tools (kiota, openapi-generator) work directly off this URL

Core endpoints

The high-traffic endpoints. Full reference in the OpenAPI spec.

Documents

EndpointMethodPurpose
/documentsGETList documents in your team
/documentsPOSTCreate a new document (upload PDF)
/documents/{id}GETGet a document by ID
/documents/{id}DELETEDelete a document
/documents/{id}/sendPOSTSend the document for signature
/documents/{id}/duplicatePOSTClone a document
/documents/{id}/recipientsGET / POSTManage recipients
/documents/{id}/fieldsGET / POSTManage fields

Templates

EndpointMethodPurpose
/templatesGETList templates
/templatesPOSTCreate a template
/templates/{id}/generatePOSTSend a document from a template
/templates/{id}/direct-linkPOSTGet the public direct link URL

Webhooks

EndpointMethodPurpose
/webhooksGET / POSTList + create webhook subscriptions
/webhooks/{id}PATCH / DELETEUpdate / remove

See Webhooks reference for the event schema.

Quick example: create + send a document

# 1. Upload a PDF and create a document
curl -X POST https://sign.pacta.ink/api/v1/documents \
  -H "Authorization: api_..." \
  -H "Content-Type: multipart/form-data" \
  -F "file=@./contract.pdf" \
  -F "title=Q4 vendor agreement" \
  -F "recipients[0][name]=John Doe" \
  -F "recipients[0][email]=john@acme.com" \
  -F "recipients[0][role]=SIGNER"
# Response: { "id": 42, "status": "DRAFT", ... }

# 2. Place a signature field (continuing with document id 42)
curl -X POST https://sign.pacta.ink/api/v1/documents/42/fields \
  -H "Authorization: api_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SIGNATURE",
    "page": 1,
    "x": 100,
    "y": 600,
    "width": 200,
    "height": 50,
    "recipientId": <recipient_id>
  }'

# 3. Send for signature
curl -X POST https://sign.pacta.ink/api/v1/documents/42/send \
  -H "Authorization: api_..."
# Response: { "id": 42, "status": "PENDING", ... }

The recipient now gets an email with the signing link. Status updates flow back to your system via webhooks.

For TypeScript / JavaScript projects, generate a typed client from the OpenAPI spec:

npx openapi-typescript https://sign.pacta.ink/api/v1/openapi \
  -o ./src/pacta-api.ts

Then use with openapi-fetch:

import createClient from 'openapi-fetch';
import type { paths } from './pacta-api';

const pacta = createClient<paths>({
  baseUrl: 'https://sign.pacta.ink/api/v1',
  headers: { Authorization: process.env.PACTA_API_TOKEN! },
});

const { data, error } = await pacta.GET('/documents', {
  params: { query: { status: 'PENDING' } },
});

You get end-to-end types — request bodies, response shapes, query params, error responses — all from a single command.

Rate limits

The API enforces per-token rate limits:

  • General endpoints: 100 requests / minute / token
  • Document send: 30 sends / minute / token
  • Webhook delivery retries: exponential backoff up to 24 hours; see Webhooks for details

If you hit a limit, the response is 429 Too Many Requests with a Retry-After header. Back off, then retry.

For higher volume (more than 100/min sustained), contact us hello@pacta.ink — Enterprise tier gets custom rate limits.

Errors

The API returns standard HTTP status codes:

  • 200/201 — success
  • 400 — bad input (validation error in body or query params)
  • 401 — missing / invalid Authorization header
  • 403 — token doesn’t have access to the resource (cross-team access, deleted document, etc.)
  • 404 — resource doesn’t exist
  • 429 — rate limited
  • 5xx — server error (you can retry; we track these and respond)

Error responses are JSON:

{
  "code": "VALIDATION_ERROR",
  "message": "recipient.email is required",
  "details": { "field": "recipients[0].email" }
}

The code is stable across requests — safe to switch on it in your client code.

Embedded signing (Business+)

If you want signers to sign inside your own product (not via the Pacta-hosted page), use embedded signing:

  1. Create a document via the API
  2. Generate a recipient-specific embed token (POST /documents/{id}/recipients/{id}/embed-token)
  3. Drop the token into our React SDK or iframe URL
  4. Your customers sign without ever seeing the Pacta domain

The full embedded signing guide is at Embedded signing (coming in v1.1). For now, contact us for the implementation details.

Where to go next

Have a question this doc didn't answer? Email us and we'll fix it.