Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.linkutm.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

UTM templates are reusable sets of UTM values (source, medium, campaign, term, content) saved to a workspace. They are referenced from Create link via templateId to pre-fill UTM fields. Every endpoint lives under /api/v1/templates, requires a JWT, and is workspace-scoped.
Authorization: Bearer <jwt>
x-workspace-id: <uuid_or_slug>

Template fields

FieldTypeNotes
idstring (UUID)Server-generated.
namestringTemplate label.
descriptionstring | nullInternal context.
utmSourcestring | nullPre-fill value for utm_source.
utmMediumstring | nullPre-fill value for utm_medium.
utmCampaignstring | nullPre-fill value for utm_campaign.
utmTermstring | nullPre-fill value for utm_term.
utmContentstring | nullPre-fill value for utm_content.
usageCountintegerTimes the template has been applied. Drives the most-used ranking.
isActivebooleanActive templates sort first and are the only ones returned by most-used.
workspaceIdstring (UUID)Set on creation; immutable.
createdByIdstring (UUID)User who created the template.
updatedByIdstring (UUID) | nullUser who last updated the template.
createdAttimestampUTC.
updatedAttimestampUTC.
The customUtmParams field is accepted in the request body interface but is not persisted on the template record. Set custom UTM keys directly on the link instead.

Create a template

POST /api/v1/templates

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes
x-workspace-id: <uuid_or_slug>YesTarget workspace
Content-Type: application/jsonYes

Body

name
string
required
Template label.
description
string
Internal context.
utmSource
string
UTM source pre-fill, e.g., google.
utmMedium
string
UTM medium pre-fill, e.g., cpc.
utmCampaign
string
UTM campaign pre-fill, e.g., q2_launch.
utmTerm
string
UTM term pre-fill.
utmContent
string
UTM content pre-fill.
customUtmParams
object
Accepted by the request interface but not stored on the template record.

Example request

curl -X POST https://api.linkutm.com/api/v1/templates \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Google Search - Brand",
    "description": "Brand search campaigns",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "q2_launch"
  }'

Example response

{
  "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
  "name": "Google Search - Brand",
  "description": "Brand search campaigns",
  "utmSource": "google",
  "utmMedium": "cpc",
  "utmCampaign": "q2_launch",
  "utmTerm": null,
  "utmContent": null,
  "usageCount": 0,
  "isActive": true,
  "workspaceId": "8a7b6c5d-...",
  "createdById": "1a2b3c4d-...",
  "updatedById": null,
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T10:00:00.000Z"
}

Errors

CodeWhen
400Validation failure
401Missing or invalid JWT
403Workspace UTM template maximum reached - the message reports used and limit counts and asks you to upgrade the plan
404Workspace not found

List templates

GET /api/v1/templates
Returns templates for the workspace, paginated. Active templates sort first, then newest first.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes
x-workspace-id: <uuid_or_slug>YesTarget workspace

Query parameters

page
integer
default:"1"
Page number.
limit
integer
default:"20"
Items per page.
Case-insensitive substring match against name, description, utmSource, utmMedium, and utmCampaign.

Example request

curl https://api.linkutm.com/api/v1/templates?page=1&limit=20&search=google \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex"

Example response

{
  "templates": [
    {
      "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
      "name": "Google Search - Brand",
      "description": "Brand search campaigns",
      "utmSource": "google",
      "utmMedium": "cpc",
      "utmCampaign": "q2_launch",
      "utmTerm": null,
      "utmContent": null,
      "usageCount": 12,
      "isActive": true,
      "workspaceId": "8a7b6c5d-...",
      "createdById": "1a2b3c4d-...",
      "updatedById": null,
      "createdAt": "2026-05-07T10:00:00.000Z",
      "updatedAt": "2026-05-07T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "pages": 1
  }
}

Errors

CodeWhen
401Missing or invalid JWT

Most used templates

GET /api/v1/templates/most-used
Returns the workspace’s active templates ranked by usageCount descending. Only templates with isActive=true are included.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes
x-workspace-id: <uuid_or_slug>YesTarget workspace

Query parameters

limit
integer
default:"5"
Number of templates to return.

Example request

curl https://api.linkutm.com/api/v1/templates/most-used?limit=5 \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex"

Example response

[
  {
    "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
    "name": "Google Search - Brand",
    "description": "Brand search campaigns",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "q2_launch",
    "utmTerm": null,
    "utmContent": null,
    "usageCount": 12,
    "isActive": true,
    "workspaceId": "8a7b6c5d-...",
    "createdById": "1a2b3c4d-...",
    "updatedById": null,
    "createdAt": "2026-05-07T10:00:00.000Z",
    "updatedAt": "2026-05-07T10:00:00.000Z"
  }
]
The response is a plain array, not a paginated envelope.

Errors

CodeWhen
401Missing or invalid JWT

Get a template

GET /api/v1/templates/:id
Returns one template by ID. This endpoint does not check the x-workspace-id header against the template’s workspace, but it is still recommended to send it for consistency.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes

Example request

curl https://api.linkutm.com/api/v1/templates/5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TOKEN"

Example response

{
  "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
  "name": "Google Search - Brand",
  "description": "Brand search campaigns",
  "utmSource": "google",
  "utmMedium": "cpc",
  "utmCampaign": "q2_launch",
  "utmTerm": null,
  "utmContent": null,
  "usageCount": 12,
  "isActive": true,
  "workspaceId": "8a7b6c5d-...",
  "createdById": "1a2b3c4d-...",
  "updatedById": null,
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T10:00:00.000Z"
}

Errors

CodeWhen
401Missing or invalid JWT
404Template not found

Update a template

PATCH /api/v1/templates/:id
Updates a template. All body fields are optional. The user making the request is recorded as updatedById.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes
Content-Type: application/jsonYes

Body

name
string
Template label.
description
string
Internal context.
utmSource
string
UTM source pre-fill.
utmMedium
string
UTM medium pre-fill.
utmCampaign
string
UTM campaign pre-fill.
utmTerm
string
UTM term pre-fill.
utmContent
string
UTM content pre-fill.
customUtmParams
object
Accepted by the request interface but not persisted.
Fields you omit are passed through to the update as undefined, which leaves the stored value unchanged. Fields you send with an explicit value overwrite the stored value.

Example request

curl -X PATCH https://api.linkutm.com/api/v1/templates/5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Google Search - Brand v2", "utmContent": "headline_a" }'

Example response

{
  "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
  "name": "Google Search - Brand v2",
  "description": "Brand search campaigns",
  "utmSource": "google",
  "utmMedium": "cpc",
  "utmCampaign": "q2_launch",
  "utmTerm": null,
  "utmContent": "headline_a",
  "usageCount": 12,
  "isActive": true,
  "workspaceId": "8a7b6c5d-...",
  "createdById": "1a2b3c4d-...",
  "updatedById": "1a2b3c4d-...",
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T11:00:00.000Z"
}

Errors

CodeWhen
401Missing or invalid JWT
404Template not found

Delete a template

DELETE /api/v1/templates/:id
Deletes a template. Deletion is blocked while the template is still in use.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes

Behavior

  • If any link still has templateId set to this template, the request fails with 400. The message reports how many links reference it.
  • If usageCount is greater than 0, the request fails with 400 even when no link currently references it.
  • Clear the UTM parameters on the linked links or delete those links before removing the template.

Example request

curl -X DELETE https://api.linkutm.com/api/v1/templates/5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TOKEN"

Example response

Returns the deleted template record.
{
  "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
  "name": "Google Search - Brand",
  "description": "Brand search campaigns",
  "utmSource": "google",
  "utmMedium": "cpc",
  "utmCampaign": "q2_launch",
  "utmTerm": null,
  "utmContent": null,
  "usageCount": 0,
  "isActive": true,
  "workspaceId": "8a7b6c5d-...",
  "createdById": "1a2b3c4d-...",
  "updatedById": null,
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T10:00:00.000Z"
}

Errors

CodeWhen
400Template is referenced by one or more links, or usageCount is greater than 0
401Missing or invalid JWT
404Template not found

Increment usage count

POST /api/v1/templates/:id/use
Increments the template’s usageCount by 1. Call this when a template is applied to a link so it ranks in Most used templates.

Headers

HeaderRequiredNotes
Authorization: Bearer <jwt>Yes

Example request

curl -X POST https://api.linkutm.com/api/v1/templates/5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d/use \
  -H "Authorization: Bearer $TOKEN"

Example response

Returns the updated template record with the incremented usageCount.
{
  "id": "5f3b2a1c-4d6e-4a8b-9c0d-1e2f3a4b5c6d",
  "name": "Google Search - Brand",
  "description": "Brand search campaigns",
  "utmSource": "google",
  "utmMedium": "cpc",
  "utmCampaign": "q2_launch",
  "utmTerm": null,
  "utmContent": null,
  "usageCount": 13,
  "isActive": true,
  "workspaceId": "8a7b6c5d-...",
  "createdById": "1a2b3c4d-...",
  "updatedById": null,
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T12:00:00.000Z"
}
The request body is ignored - the increment applies to the template named in the path. Note that a non-zero usageCount blocks deletion of the template.

Errors

CodeWhen
401Missing or invalid JWT
404Template not found