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:
- In Pacta → switch to the team you want to issue documents from
- Team Settings → API Tokens → + New token
- Name the token (e.g., “Production server”, “Staging webhooks”)
- Pick expiration (
never,7 days,30 days,90 days,1 year) - 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
| Endpoint | Method | Purpose |
|---|---|---|
/documents | GET | List documents in your team |
/documents | POST | Create a new document (upload PDF) |
/documents/{id} | GET | Get a document by ID |
/documents/{id} | DELETE | Delete a document |
/documents/{id}/send | POST | Send the document for signature |
/documents/{id}/duplicate | POST | Clone a document |
/documents/{id}/recipients | GET / POST | Manage recipients |
/documents/{id}/fields | GET / POST | Manage fields |
Templates
| Endpoint | Method | Purpose |
|---|---|---|
/templates | GET | List templates |
/templates | POST | Create a template |
/templates/{id}/generate | POST | Send a document from a template |
/templates/{id}/direct-link | POST | Get the public direct link URL |
Webhooks
| Endpoint | Method | Purpose |
|---|---|---|
/webhooks | GET / POST | List + create webhook subscriptions |
/webhooks/{id} | PATCH / DELETE | Update / 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.
TypeScript client (recommended)
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— success400— bad input (validation error in body or query params)401— missing / invalidAuthorizationheader403— token doesn’t have access to the resource (cross-team access, deleted document, etc.)404— resource doesn’t exist429— rate limited5xx— 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:
- Create a document via the API
- Generate a recipient-specific embed token (
POST /documents/{id}/recipients/{id}/embed-token) - Drop the token into our React SDK or iframe URL
- 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
- Webhooks — the other half of API integration: listening to events
- How Pacta signatures hold up — understanding what your API-created documents will be once signed