DataPublisher API v2.4

A REST API for document automation: manage templates and data, run Domain Apps, collect data with DataRequests, send for e-signature, and distribute by email. The current OpenAPI 2.4.0 specification documents 128 operations across 14 groups.

Base URLs

Production: https://app.datapublisher.io/api
Local development: http://localhost:3001/api

Authentication

The API uses JWT bearer tokens. Registration is gated by a 6-digit registration code; after that you sign in with your username and password and send the token on every protected request.

1. Get a registration code

Ask for a registration code to be emailed to you:

POST https://app.datapublisher.io/api/auth/registration-code/email
Content-Type: application/json

{ "email": "user@example.com" }

2. Register

POST https://app.datapublisher.io/api/auth/register
Content-Type: application/json

{
  "username": "jdoe",
  "email": "user@example.com",
  "password": "at-least-8-characters",
  "registrationCode": "123456",
  "firstName": "John",
  "lastName": "Doe"
}

3. Sign in and use the token

POST https://app.datapublisher.io/api/auth/login
Content-Type: application/json

{ "username": "jdoe", "password": "your-password" }

--> 200
{
  "message": "Login successful",
  "user": { "id": "...", "username": "jdoe", "email": "user@example.com", "firstName": "John", "lastName": "Doe" },
  "token": "eyJhbGciOi..."
}

Authorization: Bearer <token>

Token lifetime

Tokens expire after 24 hours. Call POST /api/auth/login again to get a new one. GET /api/auth/validate returns { "valid": true, "user": { ... } } for a live token, and POST /api/auth/logout ends the session.
Auth endpointPurpose
POST /api/auth/change-passwordChange password (signed in)
POST /api/auth/forgot-passwordEmail a password-reset link (public)
POST /api/auth/reset-passwordSet a new password using the emailed token (public)

Security note

Keep tokens out of client-side code and browser-visible storage. Recipient-facing DataRequest endpoints use their own single-purpose link token, never your bearer token.

Rate limits

Limits apply per client IP in a 15-minute window:

CategoryRequests / 15 minApplies to
General API1,000All /api endpoints
Authentication20/api/auth/*
File uploads50/api/csv uploads

When a limit is exceeded the API returns 429 Too Many Requests. Wait for the window to reset before retrying.

Errors

Use the HTTP status code first; the JSON body carries a human-readable message.

CodeMeaning
200 / 201Success / created
400Invalid or missing input (validation failures include an errors array)
401Missing, invalid, or expired token, or wrong credentials
403Authenticated but not allowed (for example, a subscription or ownership check)
404Resource not found
429Rate limit exceeded
500Server error

Error bodies are JSON with a single consistent shape:

{ "success": false, "error": "templateId is required", "message": "templateId is required" }

{ "success": false, "error": "Validation failed: 6-digit registration code required",
  "message": "Validation failed: 6-digit registration code required",
  "errors": [ { "msg": "...", "path": "registrationCode" } ] }

Read error for display and log the status code. message is kept as an alias of error for older clients; validation failures also include an errors array from the field-level checks.

API groups

The 2.4 specification organizes 128 operations into these groups:

GroupOperationsWhat it coversBase path
Auth8Registration code by email, register, login, logout, validate, password change and reset/api/auth
Documents8Template document library: upload, list, categories, content and merge tokens, download/api/documents
Word Templates6Upload and list .docx templates/api/word-templates
CSV15Data-file upload and management, relationships, refresh/api/csv
Data Sets20Named bundles of data files and templates, with subresources/api/data-sets
Data Sources3Google Sheets, Microsoft Excel, and SQL Server connectors/api/datasources
Sync4Scheduled data-refresh schedules and on-demand sync/api/sync
Email Campaigns19Campaign setup, email body generation, broadcast/api/email-campaigns
DataRequest22Shareable data-collection links: create, recipient submit, resend, revoke, legal hold, audit trail/api/form-invitations
E-Signature2Create and check native e-signature requests/api/esignature
Domains13Domain App verticals: catalog, templates, columns, filters and response-link schemas/api/domains
CRM4Contacts and per-contact activity feed/api/crm
Lead Intelligence2Captured leads/api/leads
Mirror Mode2Live merge preview sessions (split-pane document/data sync)/api/mirror

Endpoints marked public need no bearer token: Domain App catalog reads and the recipient side of DataRequests. Everything else requires Authorization: Bearer <token>. Capability-pack and other integration endpoints are not yet part of this reference.

DataRequest API

A DataRequest sends a recipient a secure, expiring link to a form. The sender creates and manages requests with a bearer token; the recipient works with the link token and needs no account. The same workflow is available in Word under Actions → DataRequest (see Getting Started).

Create a DataRequest

POST https://app.datapublisher.io/api/form-invitations
Authorization: Bearer <token>
Content-Type: application/json

{
  "formType": "event_registration",
  "operation": "create",
  "recipientEmail": "attendee@example.com",
  "recipientName": "Pat Attendee",
  "expiresInDays": 7,
  "sendEmail": true
}

--> 200
{
  "success": true,
  "inviteId": "b3f0...",
  "shareableUrl": "https://app.datapublisher.io/...",
  "expiresAt": "2026-09-26T14:00:00.000Z",
  "emailSent": true
}

formType, operation, and recipientEmail are required. formType is a form definition id such as event_registration, volunteer_registration, or student_enrollment; operation is what the recipient may do: create, edit, view, or review_submit. expiresInDays defaults to 30 and sendEmail to false; set it to have the invitation emailed through Microsoft Graph. An optional metadata object carries the document title and content.

Lifecycle endpoints

EndpointWhoPurpose
POST /api/form-invitationsSenderCreate one request
POST /api/form-invitations/batchSenderCreate several requests in one call
POST /api/form-invitations/preview-emailSenderPreview the invitation email without sending
GET /api/form-invitations/{inviteId}SenderGet one request
GET /api/form-invitations/{inviteId}/submissionSenderRead the submitted answers
POST /api/form-invitations/{inviteId}/resendSenderRe-send the invitation email
POST /api/form-invitations/{inviteId}/revokeSenderRevoke; the link stops working
PUT|DELETE /api/form-invitations/{inviteId}/legal-holdSenderPlace or remove a legal hold
GET /api/form-invitations/{inviteId}/audit-trailSenderFull audit trail
GET /api/form-invitations/{inviteId}/view-emailSenderThe original sent email HTML, for compliance
PATCH /api/form-invitations/{inviteId}/archiveSenderArchive; /unarchive reverses it
GET /api/form-invitations/validateRecipientValidate a link token
GET|POST /api/form-invitations/{token}/draftRecipientLoad or save a draft
POST /api/form-invitations/{token}/submitRecipientSubmit the completed form
POST /api/form-invitations/{token}/generate-documentRecipientGenerate the response document after submission

Recipient endpoints authenticate with the link token and do not take a bearer token. Approval, return-for-correction, and CSV write-back happen in the Word task pane and are not separate public endpoints.

E-signature, CRM, and more (planned)

The endpoints below are on the roadmap and marked x-status: planned in the OpenAPI spec — they are not implemented yet and will 404 if called today. E-signature is currently handled inline as part of the DataRequest workflow (see the DataRequest API section above), and native CRM/lead capture live under the capability-pack API, not at these paths.

EndpointPurpose
POST /api/esignature/requestsCreate an e-signature request. Body: documentId, signerEmail, optional signerName
GET /api/esignature/requests/{requestId}Check signing status
GET|POST /api/crm/contactsList or create CRM contacts
GET /api/crm/contacts/{contactId}Get a contact; /activity returns its activity feed
GET /api/leadsList captured leads; /api/leads/{leadId} gets one
POST /api/mirror/sessionStart a live merge preview. Body: dataSetId, templateId
DELETE /api/mirror/session/{sessionId}End the preview session
GET /api/domainsList Domain Apps (public); templates, columns, and filters are under /api/domains/{domainId}/...

Code examples

Sign in, then create a DataRequest.

cURL

# cURL
TOKEN=$(curl -s -X POST https://app.datapublisher.io/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"jdoe","password":"your-password"}' | jq -r .token)

curl -X POST https://app.datapublisher.io/api/form-invitations \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"formType":"event_registration","operation":"create","recipientEmail":"attendee@example.com","sendEmail":true}'

JavaScript

// JavaScript (Node 18+)
const BASE = 'https://app.datapublisher.io/api';

async function api(path, { token, ...opts } = {}) {
  const res = await fetch(BASE + path, {
    ...opts,
    headers: { 'Content-Type': 'application/json', ...(token && { Authorization: `Bearer ${token}` }) },
  });
  const body = await res.json();
  if (!res.ok) throw new Error(body.message || body.error?.message || body.error || res.status);
  return body;
}

const { token } = await api('/auth/login', {
  method: 'POST', body: JSON.stringify({ username: 'jdoe', password: 'your-password' }),
});

const invite = await api('/form-invitations', {
  method: 'POST', token,
  body: JSON.stringify({ formType: 'event_registration', operation: 'create',
                         recipientEmail: 'attendee@example.com', expiresInDays: 7, sendEmail: true }),
});
console.log(invite.shareableUrl);

Python

# Python
import requests

BASE = 'https://app.datapublisher.io/api'

login = requests.post(f'{BASE}/auth/login', json={'username': 'jdoe', 'password': 'your-password'})
login.raise_for_status()
token = login.json()['token']

resp = requests.post(
    f'{BASE}/form-invitations',
    headers={'Authorization': f'Bearer {token}'},
    json={'formType': 'event_registration', 'operation': 'create',
          'recipientEmail': 'attendee@example.com', 'expiresInDays': 7, 'sendEmail': True},
)
resp.raise_for_status()
print(resp.json()['shareableUrl'])

Resources

Guides

Per-area guides for authentication, data sources, documents, and email.

Browse the guides →

Authentication guide

Registration and sign-in flows in more detail.

Read the guide →

Roadmap

What is planned for the API.

See the roadmap →

The area guides were written for an earlier API version and do not yet cover DataRequests, e-signature, CRM, or Mirror Mode; this page is the current overview.