API Reference
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
https://app.datapublisher.io/api
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
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 endpoint | Purpose |
|---|---|
POST /api/auth/change-password | Change password (signed in) |
POST /api/auth/forgot-password | Email a password-reset link (public) |
POST /api/auth/reset-password | Set a new password using the emailed token (public) |
Security note
Rate limits
Limits apply per client IP in a 15-minute window:
| Category | Requests / 15 min | Applies to |
|---|---|---|
| General API | 1,000 | All /api endpoints |
| Authentication | 20 | /api/auth/* |
| File uploads | 50 | /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.
| Code | Meaning |
|---|---|
200 / 201 | Success / created |
400 | Invalid or missing input (validation failures include an errors array) |
401 | Missing, invalid, or expired token, or wrong credentials |
403 | Authenticated but not allowed (for example, a subscription or ownership check) |
404 | Resource not found |
429 | Rate limit exceeded |
500 | Server 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:
| Group | Operations | What it covers | Base path |
|---|---|---|---|
| Auth | 8 | Registration code by email, register, login, logout, validate, password change and reset | /api/auth |
| Documents | 8 | Template document library: upload, list, categories, content and merge tokens, download | /api/documents |
| Word Templates | 6 | Upload and list .docx templates | /api/word-templates |
| CSV | 15 | Data-file upload and management, relationships, refresh | /api/csv |
| Data Sets | 20 | Named bundles of data files and templates, with subresources | /api/data-sets |
| Data Sources | 3 | Google Sheets, Microsoft Excel, and SQL Server connectors | /api/datasources |
| Sync | 4 | Scheduled data-refresh schedules and on-demand sync | /api/sync |
| Email Campaigns | 19 | Campaign setup, email body generation, broadcast | /api/email-campaigns |
| DataRequest | 22 | Shareable data-collection links: create, recipient submit, resend, revoke, legal hold, audit trail | /api/form-invitations |
| E-Signature | 2 | Create and check native e-signature requests | /api/esignature |
| Domains | 13 | Domain App verticals: catalog, templates, columns, filters and response-link schemas | /api/domains |
| CRM | 4 | Contacts and per-contact activity feed | /api/crm |
| Lead Intelligence | 2 | Captured leads | /api/leads |
| Mirror Mode | 2 | Live 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
| Endpoint | Who | Purpose |
|---|---|---|
POST /api/form-invitations | Sender | Create one request |
POST /api/form-invitations/batch | Sender | Create several requests in one call |
POST /api/form-invitations/preview-email | Sender | Preview the invitation email without sending |
GET /api/form-invitations/{inviteId} | Sender | Get one request |
GET /api/form-invitations/{inviteId}/submission | Sender | Read the submitted answers |
POST /api/form-invitations/{inviteId}/resend | Sender | Re-send the invitation email |
POST /api/form-invitations/{inviteId}/revoke | Sender | Revoke; the link stops working |
PUT|DELETE /api/form-invitations/{inviteId}/legal-hold | Sender | Place or remove a legal hold |
GET /api/form-invitations/{inviteId}/audit-trail | Sender | Full audit trail |
GET /api/form-invitations/{inviteId}/view-email | Sender | The original sent email HTML, for compliance |
PATCH /api/form-invitations/{inviteId}/archive | Sender | Archive; /unarchive reverses it |
GET /api/form-invitations/validate | Recipient | Validate a link token |
GET|POST /api/form-invitations/{token}/draft | Recipient | Load or save a draft |
POST /api/form-invitations/{token}/submit | Recipient | Submit the completed form |
POST /api/form-invitations/{token}/generate-document | Recipient | Generate 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.
| Endpoint | Purpose |
|---|---|
POST /api/esignature/requests | Create an e-signature request. Body: documentId, signerEmail, optional signerName |
GET /api/esignature/requests/{requestId} | Check signing status |
GET|POST /api/crm/contacts | List or create CRM contacts |
GET /api/crm/contacts/{contactId} | Get a contact; /activity returns its activity feed |
GET /api/leads | List captured leads; /api/leads/{leadId} gets one |
POST /api/mirror/session | Start a live merge preview. Body: dataSetId, templateId |
DELETE /api/mirror/session/{sessionId} | End the preview session |
GET /api/domains | List 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
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.