REST API

Variables API

API v115 August 2026·5 min read

Full reference for Doclift's Variables API: field types, allowed_values, and inline creation on a template.

The variable object

  • id: unique identifier
  • title: name of the variable, unique within its template
  • description: required, explains the expected content
  • field_type: text, checkbox, radio, select, or collection
  • seed_value: sample value for previewing the template. Never returned by these endpoints; only the template create/update/publish/unpublish detail view returns it, see Templates API
  • allowed_values: array, only meaningful on radio/select

collection is a field type built for workflow templates, where a dedicated API accepts a fields array describing each row. This endpoint's permitted parameters are title, description, seed_value, field_type, and allowed_values only. fields is not one of them, so a collection variable created here has no way to satisfy the row-description validation it requires and cannot be created through this endpoint.

Every action below first resolves the parent template through the same scope as the templates write endpoints: custom, not archived, in your organization. A fillable_form or workflow template id, an archived one, or one belonging to another organization all answer 404 {"error": "Template not found"}. See Writes only reach custom templates.


Titles are not normalised on a brand-new variable

Normalisation only applies once a variable already exists

A variable's title is downcased and stripped only when you update an already-persisted variable (PATCH .../variables/:id). A brand-new variable keeps whatever case and whitespace you send it in, whether it is created through POST .../variables, through variables_attributes on POST /api/v1/templates, or through variables_attributes on PATCH /api/v1/templates/:id (adding a new variable there behaves like a create, not an update, even though the request itself is a PATCH). Do not rely on case-insensitive variable names: a title's case and whitespace are preserved exactly as sent on creation, and are only normalised the first time that variable is itself updated.

title must match a naming pattern (letters, digits, underscores; no spaces or accents) and must be unique within its template, on both create and update.


List variables

GET/api/v1/templates/:template_id/variables
cURL
curl https://app.doclift.io/api/v1/templates/100013/variables \
  --header "X-Api-Key: <your-api-key>"
200 OK · application/json
[
  {
    "id": 200003,
    "title": "client_name",
    "description": "Name of the client",
    "field_type": "text",
    "allowed_values": []
  },
  {
    "id": 200004,
    "title": "status",
    "description": "Client status",
    "field_type": "select",
    "allowed_values": ["active", "inactive", "pending"]
  }
]

Returns every variable of the template (no pagination). seed_value is deliberately absent from this shape.

StatusBodyWhen
200 arraysuccess
404 {"error": "Template not found"}not custom, archived, or another organization's
403 {"error": "..."}missing, unknown, or disabled API key

Create a variable

POST/api/v1/templates/:template_id/variables
cURL
curl https://app.doclift.io/api/v1/templates/100013/variables \
  --request POST \
  --header "X-Api-Key: <your-api-key>" \
  --header "Content-Type: application/json" \
  --data '{
    "variable": {
      "title": "payment_method",
      "description": "Selected payment method",
      "field_type": "select",
      "seed_value": "bank_transfer",
      "allowed_values": ["bank_transfer", "credit_card", "check"]
    }
  }'
201 Created · application/json
{
  "id": 200005,
  "title": "payment_method",
  "description": "Selected payment method",
  "field_type": "select",
  "allowed_values": ["bank_transfer", "credit_card", "check"]
}

seed_value is accepted in the request body but never present in the response of this endpoint (see the callout above for where it is readable).

FieldTypeRequiredNotes
titlestringyesunique per template, naming pattern enforced
descriptionstringyes
field_typestringnoone of the five values, default text
seed_valuestringnomust be one of allowed_values if both are set
allowed_valuesarrayno
StatusBodyWhen
201 variablesuccess
422 {"errors": ["..."]}missing title/description, duplicate title, unknown field_type, invalid title pattern, or seed_value outside allowed_values
404 {"error": "Template not found"}not custom, archived, or another organization's
403 {"error": "..."}missing, unknown, or disabled API key

Update a variable

PATCH/api/v1/templates/:template_id/variables/:id
cURL
curl https://app.doclift.io/api/v1/templates/100013/variables/200005 \
  --request PATCH \
  --header "X-Api-Key: <your-api-key>" \
  --header "Content-Type: application/json" \
  --data '{
    "variable": {
      "description": "Updated description",
      "allowed_values": ["bank_transfer", "credit_card"]
    }
  }'
200 OK · application/json
{
  "id": 200005,
  "title": "payment_method",
  "description": "Updated description",
  "field_type": "select",
  "allowed_values": ["bank_transfer", "credit_card"]
}

Same fields as create. allowed_values replaces the stored array, it does not merge with it. Renaming title here is lowercased and stripped (unlike create). Promoting field_type (e.g. text to select) while setting allowed_values in the same call works.

Narrowing allowed_values below the stored seed_value is refused

If the variable already has a seed_value, an update that shrinks allowed_values to no longer contain it answers 422 and leaves the stored allowed_values unchanged.

StatusBodyWhen
200 variablesuccess
422 {"errors": ["..."]}same validations as create, plus the narrowing case above
404 {"error": "Template not found"}not custom, archived, or another organization's
404 {"error": "Variable not found"}the id does not belong to this template
403 {"error": "..."}missing, unknown, or disabled API key

Delete a variable

DELETE/api/v1/templates/:template_id/variables/:id
cURL
curl https://app.doclift.io/api/v1/templates/100013/variables/200005 \
  --request DELETE \
  --header "X-Api-Key: <your-api-key>"

204 No Content. This is a hard delete (no validation runs), so there is no 422 path here.

StatusBodyWhen
204 nonesuccess
404 {"error": "Template not found"}not custom, archived, or another organization's
404 {"error": "Variable not found"}the id does not belong to this template
403 {"error": "..."}missing, unknown, or disabled API key

Creating a variable inline

Instead of a separate call, variables_attributes on POST /api/v1/templates or PATCH /api/v1/templates/:id accepts the same fields (title, description, seed_value, field_type, allowed_values) plus id and _destroy for update. See Templates API for the request shape. The response of these template endpoints is the one place a variable's id and seed_value appear together.

The same not-normalised behaviour applies to a brand-new variable added through variables_attributes, whether on POST /api/v1/templates or on PATCH /api/v1/templates/:id. Only a variable that already existed before the call gets its title lowercased and stripped.