Templates
Template endpoints allow you to manage design templates for QR codes and pages.
List Templates
Get a list of templates. There are two endpoints:
- Public templates:
GET https://v1.freeqr.io/api/templates- Returns public templates (visibility = 1) - Project templates:
GET https://v1.freeqr.io/api/projects/{project}/templates- Returns templates in a specific project
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 10, max: 100) |
sort | string | No | Sort field (default: order) |
filters[type] | integer | Yes | Filter by template type (required). Values: 1 (PAGE_DESIGN), 2 (QR_DESIGN) |
filters[user_id] | string | No | Filter by user ID. Use current to filter by the authenticated user's ID |
Filter Behavior
- Public templates endpoint (
GET https://v1.freeqr.io/api/templates): Returns templates with visibility = 1 (PUBLIC). Iffilters[user_id]is provided, filters by that user. Otherwise, returns all public templates. - Project templates endpoint (
GET https://v1.freeqr.io/api/projects/{project}/templates): Returns templates for the specified project. Iffilters[user_id]is provided, further filters by that user.
Response
{
"data": [
{
"id": "01arz3ndektsv4rrffq69g5fav",
"project_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"name": "My Template",
"description": null,
"type": 2,
"visibility": 1,
"current_version": 1,
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"current_template_version": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 1,
"description": null,
"visibility": 1,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
],
"meta": {
"total": 1
},
"included_files": []
}
Note:
- The
typefield is an integer enum:1= PAGE_DESIGN,2= QR_DESIGN. - The
visibilityfield is an integer enum:1= PUBLIC,2= HIDDEN,3= PRIVATE.
Create Template
Create a new template in a project.
POST https://v1.freeqr.io/api/projects/{project}/templates
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string (ULID) | Yes | Project ID |
Request Body
{
"name": "My Template",
"description": "Template description",
"type": 2,
"template_version": {
"config": {},
"description": "Initial version"
}
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name (max 255 characters) |
description | string | No | Template description (max 1000 characters) |
type | integer | Yes | Template type enum: 1 (PAGE_DESIGN), 2 (QR_DESIGN) |
template_version | object | No | Optional template version data |
template_version.config | object | No | Template version configuration (max 10KB) |
template_version.description | string | No | Template version description |
Note:
- The template is automatically assigned to the authenticated user (
user_idis set automatically) - Visibility is determined by the project settings, not set directly in the request
- Maximum 100 templates per user
- Plan-based limits apply for templates per project
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"project_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"name": "My Template",
"description": "Template description",
"type": 2,
"visibility": 1,
"current_version": 1,
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"current_template_version": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"version": 1,
"config": {},
"description": "Initial version",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
}
Note: If template_version is provided in the request, a version will be created and current_version will be 1. If not provided, current_version will be 0 and current_template_version will be null.
Get Template
Get a specific template by ID.
GET https://v1.freeqr.io/api/templates/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template ID |
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"project_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"name": "My Template",
"description": "Template description",
"type": 2,
"visibility": 1,
"current_version": 0,
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"current_template_version": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"version": 1,
"config": {},
"description": "Initial version",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
}
Update Template
Update an existing template.
PATCH https://v1.freeqr.io/api/templates/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template ID |
Request Body
{
"name": "Updated Template",
"description": "Updated description",
"visibility": 3,
"template_version": {
"config": {},
"description": "Updated version"
}
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | Template name (max 255 characters) |
description | string | No | Template description (max 1000 characters) |
visibility | integer | No | Visibility enum: 1 (PUBLIC), 2 (HIDDEN), 3 (PRIVATE) |
template_version | object | No | Optional template version data |
template_version.config | object | No | Template version configuration (max 10KB) |
template_version.description | string | No | Template version description (max 1024 characters) |
Update Behavior
Pending Review Workflow:
- If the template has
visibility = 1(PUBLIC) OR if you're changing thevisibilityfield, the update will be stored inpending_update_datafor admin review - Updates to templates with existing
pending_update_datawill be rejected with409 Conflicterror
Immediate Updates:
- For private templates without visibility changes, updates are applied immediately
- Template version updates follow the same workflow (draft for public templates, immediate for private)
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"project_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": "01arz3ndektsv4rrffq69g5fav",
"name": "Updated Template",
"description": "Updated description",
"type": 2,
"visibility": 3,
"current_version": 1,
"pending_update": false,
"pending_update_data": null,
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z",
"current_template_version": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"version": 1,
"config": {},
"description": "Updated version",
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
}
}
Note: The pending_update and pending_update_data fields are only visible to users with update permissions on the template.
Delete Template
Delete a template.
DELETE https://v1.freeqr.io/api/templates/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template ID |
Response
Returns the deleted template resource (same structure as Get Template).
List Template Versions
Get all published versions of a template (draft version with version = 0 is excluded).
GET https://v1.freeqr.io/api/templates/{template}/template_versions
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
template | string (ULID) | Yes | Template ID |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default: 1) |
limit | integer | No | Items per page (default: 10, max: 100) |
sort | string | No | Sort field (prefix with - for descending) |
Note: Results are automatically filtered to only include versions with version > 0 (published versions) and ordered by version descending (newest first).
Response
{
"data": [
{
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 2,
"description": "Updated version",
"visibility": 3,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
{
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 1,
"description": "Initial version",
"visibility": 3,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
],
"meta": {
"total": 2
},
"included_files": []
}
Note: The visibility field is an integer enum: 1 = PUBLIC, 2 = HIDDEN, 3 = PRIVATE.
Create Template Version
Create a new published version of a template. The version number is automatically assigned (incremented from the current version).
POST https://v1.freeqr.io/api/templates/{template}/template_versions
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
template | string (ULID) | Yes | Template ID |
Request Body
{
"config": {},
"description": "New version description",
"pending_visibility": 1,
"pending_visibility_review_note": "Requesting public visibility",
"preview": "preview-url"
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
config | object | No | Template version configuration (max 10KB) |
description | string | No | Version description (max 1024 characters) |
pending_visibility | integer | No | Requested visibility enum: 1 (PUBLIC), 3 (PRIVATE). Requires admin approval if set to PUBLIC. |
pending_visibility_review_note | string | No | Note for visibility review |
preview | string | No | Preview URL (max 255 characters) |
Note:
- If the template has
pending_update_data, the request will be rejected with409 Conflict - Version numbers are automatically assigned (incremented from current version)
- Setting
pending_visibilityto PUBLIC requires admin approval
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 2,
"description": "New version description",
"visibility": 3,
"pending_visibility": 1,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
"included_files": []
}
Update Draft Template Version
Update the draft version of a template (version 0). If no draft exists, one will be created automatically.
POST https://v1.freeqr.io/api/templates/{template}/template_versions:draft
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
template | string (ULID) | Yes | Template ID |
Request Body
{
"config": {},
"description": "Draft description"
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
config | object | No | Template version configuration (max 10KB) |
description | string | No | Version description (max 1024 characters) |
Note: The draft version (version 0) is automatically created if it doesn't exist. It has default visibility of PRIVATE (3).
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 0,
"description": "Draft description",
"visibility": 3,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
"included_files": []
}
Get Template Version
Get a specific template version by ID.
GET https://v1.freeqr.io/api/template_versions/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template version ID |
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 1,
"description": "Version description",
"visibility": 3,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
"included_files": []
}
Note: Draft versions have version = 0. Published versions have version > 0.
Update Template Version
Update an existing template version.
PATCH https://v1.freeqr.io/api/template_versions/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template version ID |
Request Body
{
"description": "Updated description",
"pending_visibility": 1,
"pending_visibility_review_note": "Requesting public visibility",
"preview": "preview-url"
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
description | string | No | Version description (max 1024 characters) |
pending_visibility | integer | No | Requested visibility enum: 1 (PUBLIC), 3 (PRIVATE). Requires admin approval if set to PUBLIC. |
pending_visibility_review_note | string | No | Note for visibility review |
preview | string | No | Preview URL (max 255 characters) |
Note:
- If the template has
pending_update_data, the request will be rejected with409 Conflict - The
configfield cannot be updated via this endpoint (use the draft endpoint to update config) - Setting
pending_visibilityto PUBLIC requires admin approval
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 1,
"description": "Updated description",
"visibility": 3,
"pending_visibility": 1,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
"included_files": []
}
Delete Template Version
Delete a template version.
DELETE https://v1.freeqr.io/api/template_versions/{id}
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template version ID |
Note:
- If the template has
pending_update_data, the request will be rejected with409 Conflict - The current template version (the one matching the template's
current_version) cannot be deleted and will return409 Conflict
Response
Returns the deleted template version resource (same structure as Get Template Version).
Restore Template Version
Restore a previous template version by creating a new version from it. This increments the template's current_version and assigns the restored version the next version number.
POST https://v1.freeqr.io/api/template_versions/{id}:restore
Requires Authentication: Yes
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (ULID) | Yes | Template version ID |
Note:
- If the template has
pending_update_data, the request will be rejected with409 Conflict - Draft versions (
version = 0) cannot be restored and will return400 Bad Request - If the version is already the latest version (matches the template's
current_version), no changes are made
Response
{
"data": {
"id": "01arz3ndektsv4rrffq69g5fav",
"template_id": "01arz3ndektsv4rrffq69g5fav",
"thumbnail_file_id": null,
"version": 3,
"description": "Restored version",
"visibility": 3,
"pending_visibility": null,
"config": {},
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
},
"included_files": []
}