REST API
API basics
Base URL, authentication, environments, dates, response codes, the error envelope, pagination, and GET /api/v1/user.
Base URL
Every endpoint in this documentation is relative to:
https://app.doclift.io/api/v1
Send requests directly from your server, never from a user's browser. Your API key would otherwise be exposed to whoever inspects the page.
Authentication
Every request carries an X-Api-Key header. The key identifies an
external application, which belongs to an organization. Every read and
write in this API is scoped to that organization, not to a single user or a
single key.
curl https://app.doclift.io/api/v1/templates \
-H "X-Api-Key: <your-api-key>"
A key belonging to a disabled external application answers exactly like an
unknown key: 403 Forbidden. See Response codes for the
exact bodies.
HTTP verbs
| Verb | Used for |
|---|---|
| GET | Read a resource or list one. |
| POST | Create a resource, or trigger an action (generation, publish). |
| PUT/PATCH | Update a resource. Both are accepted wherever an endpoint documents an update. |
| DELETE | Remove a resource: a soft archive on some resources, a hard delete on others; each endpoint's page says which. |
Send JSON bodies; every response is JSON.
Environments
Every external application (API key) is created in one of two environments. The two share the same templates and data; an environment is a property of the key, not of the resource it acts on.
| Sandbox | Production | |
|---|---|---|
| Available from account creation | yes | only if your organization is authorized for production mode |
| Watermarking | every generated document is watermarked | not watermarked |
| Default generation priority | forced to low (see priority) | whatever you send (default critical) |
| Quotas (document size limit, webhook retry count) | same as production (set per organization, not per environment) | same as sandbox |
Creating a production key requires your organization to be authorized for production mode; that check runs only at key-creation time, so a production key already issued keeps working even if the authorization is later revoked. There is no equivalent restriction on sandbox keys.
There is no rate limiting anywhere in this API. No request-per-minute ceiling exists to hit, in either environment.
Date format
All timestamps (created_at, updated_at, generated_at, timestamp,
and similar fields) are rendered as ISO-8601, e.g.
2024-01-15T10:30:00+01:00. The timestamp field sent in every webhook
payload is computed at response time rather than read from a stored
column, but uses the same ISO-8601 format as every other date field in
this API.
Response codes
| Code | Meaning |
|---|---|
| 200 | The request succeeded. |
| 201 | A resource was created. |
| 204 | The request succeeded; there is no response body. |
| 400 | The body is not valid JSON, or is missing its required root key (template, variable, document_request, …). |
| 403 | The X-Api-Key header is missing, unknown, or belongs to a disabled external application. |
| 404 | The resource does not exist, is not in your organization, is archived, or is not the category this endpoint operates on. |
| 409 | A workflow write is refused because the dashboard builder currently holds the edit lock on it (workflow-authoring endpoints only); templates, variables, and document requests never answer 409. |
| 422 | The request was well-formed but failed a validation or business rule. |
Errors
There is no single error envelope shared by the whole API. The shape depends on what failed:
| Situation | Status | Body |
|---|---|---|
| Missing, invalid, or disabled API key | 403 | {"error": "<message>"} |
| Malformed JSON body | 400 | {"error": "Le body de la requête semble mal formé."} |
| Missing required root key | 400 | {"error": "<names the missing param>"} |
| Model validation failure on create/update | 422 | {"errors": ["<message>", ...]} |
| Business-rule failure (e.g. creating a document request) | 422 | {"error": "<message>"}, plus invalid_variables for a fillable-form allowed-values violation |
| Resource not found | 404 | {"error": "Template not found"} / {"error": "Variable not found"} / {"error": "Record not found"} |
The key name (error vs. errors) and the not-found wording both vary by
endpoint. Match on the status code, not on a fixed body shape, if you branch
on failures programmatically.
Pagination
Two list endpoints are paginated: GET /api/v1/templates and
GET /api/v1/document_requests. Page size is fixed at 30 and cannot be
changed; add ?page= to move through the results. A page past the last one
still answers 200 with an empty array, never a 404.
Every paginated response carries these headers:
| Header | Meaning |
|---|---|
| results | Total number of records, across every page. |
| results_per_page | Records per page (30). |
| current_page | The page this response returned. |
| pages_count | Total number of pages. |
The one exception: GET /api/v1/document_requests skips pagination
entirely when your organization has zero document requests at all,
answering 200 [] with none of these headers set. There is nothing to
page through. GET /api/v1/templates always sets them, even for an empty
result.
GET /api/v1/templates/:template_id/variables is not paginated. It
always returns every variable of the template in one array.
User info
Returns the profile of the user your key resolves to (the external application's creator, or the organization's owner if that creator has been deactivated), plus your organization's account-level limits and the calling key's own public info. No parameters.
curl https://app.doclift.io/api/v1/user \
-H "X-Api-Key: <your-api-key>"
{
"id": 100001,
"firstname": "John",
"lastname": "Doe",
"email": "[email protected]",
"created_at": "2021-02-15T10:30:00+01:00",
"updated_at": "2021-06-20T14:00:00+01:00",
"document_max_length_allowed": 800000,
"webhooks_replays_count": 3,
"allowed_to_use_production_mode": false,
"current_external_application": {
"name": "My App",
"environment": "sandbox",
"active": true,
"webhook_url": "https://myapp.com/webhooks/doclift",
"revealable_secret_key": "•••...abc12345"
}
}
document_max_length_allowed, webhooks_replays_count, and
allowed_to_use_production_mode are your organization's settings, not
personal ones. Every key in the same organization reports the same values.
current_external_application never includes the raw secret_key, only the
masked revealable_secret_key.
Status codes: 200 on success, 403 per the authentication rules above.
There is no other failure mode for this endpoint.