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 rules are a single per-workspace configuration that normalizes and validates UTM values. Normalization (force lowercase, space replacement, length trimming) is applied to UTM values when links are created. Validation rules (prohibited values, allowed-character regex, required fields, conditional logic) surface errors and warnings before a value is saved. Every workspace has exactly one UTM rules record. It is created on first access with default settings. Every endpoint lives under /api/v1/utm-rules, requires a JWT, and is workspace-scoped.
Authorization: Bearer <jwt>
x-workspace-id: <uuid_or_slug>

What the rules do

Normalization (always applied first)

These three settings are applied, in order, to every UTM value before validation runs and before a link is saved.
SettingTypeDefaultEffect
forceLowercasebooleantrueConverts the value to lowercase.
spaceCharacterstring_Replaces every run of whitespace with this character. For example, Q2 Launch becomes q2_launch.
maxParameterLengthinteger100Maximum value length. On the process endpoint the value is truncated to this length. On the validate endpoint an over-length value produces an error instead.

Validation rules

SettingTypeEffect
allowedCharactersRegexstringA regular expression the processed value must match. A value that does not match produces a Value contains disallowed characters error. An invalid regex is skipped silently.
prohibitedValuesstring[]A list of banned substrings. The check is case-insensitive: if the processed value contains any prohibited term, a Value contains prohibited term error is produced.
standardizationRulesobject[]Named rules stored on the record (see Standardization rules). They are persisted by update but are not currently applied by validate or process.
requiredFieldRulesobject[]Per-field validation rules - empty checks, length checks, regex checks, allowed-value checks (see Required field rules).
conditionalLogicRulesobject[]If-then rules that auto-set one field based on the value of another (see Conditional logic rules).
isActivebooleanMaster switch. When false, validate returns valid: true with no processing, and process returns the value unchanged.

Standardization rules

Each entry in standardizationRules has this shape:
FieldTypeNotes
namestringRule label.
isActivebooleanWhether the rule is enabled.
ruleTypestringOne of trim_whitespace, remove_special_chars, replace_pattern, custom.
descriptionstringOptional explanation.
applyToParametersstring[]Parameter codes the rule targets, e.g., ["source", "medium"].
patternstringSearch pattern, used with replace_pattern.
replacementstringReplacement text, used with replace_pattern.
Standardization rules are stored and returned by the rules record, but the current validate and process logic does not apply them. Treat them as configuration that is persisted for future use.

Required field rules

Each entry in requiredFieldRules has this shape:
FieldTypeNotes
namestringRule label.
isActivebooleanInactive rules are skipped.
descriptionstringUsed as the error message when the rule fails.
validationTypestringOne of not_empty, min_length, max_length, regex, allowed_values.
requiredParametersstring[]Parameter codes the rule applies to.
minCharintegerMinimum length, used with min_length.
maxCharintegerMaximum length, used with max_length (defaults to 100 if unset).
regexstringPattern, used with regex.
allowedValuesstring[]Permitted values, used with allowed_values.
Behavior of each validationType:
  • not_empty - the field must be present and not blank.
  • min_length - if the field has a value, it must be at least minChar characters.
  • max_length - if the field has a value, it must be at most maxChar characters.
  • regex - if the field has a value, it must match regex. An invalid regex is skipped silently.
  • allowed_values - if the field has a value, it must be one of allowedValues.
When a check fails, the rule’s description is used as the error message if set, otherwise a generated default message is used.

Conditional logic rules

Each entry in conditionalLogicRules has this shape:
FieldTypeNotes
ifFieldstringParameter code to test.
ifValuestringValue to compare against.
conditionstringOne of equals, contains, starts_with, ends_with, not_empty.
thenSetstringParameter code to set when the condition is met.
toValuestringValue to set thenSet to.
When a condition is met during validation, thenSet is overwritten with toValue in processedParams and a warning is added describing the auto-set. Conditional rules run after normalization and required-field checks.

Get UTM rules

GET /api/v1/utm-rules
Returns the workspace’s UTM rules. If no record exists yet, one is created with default settings and returned. This is a get-or-create endpoint.

Headers

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

Example request

curl https://api.linkutm.com/api/v1/utm-rules \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex"

Example response

{
  "id": "r-uuid",
  "workspaceId": "8a7b6c5d-...",
  "spaceCharacter": "_",
  "forceLowercase": true,
  "maxParameterLength": 100,
  "allowedCharactersRegex": null,
  "prohibitedValues": [],
  "standardizationRules": [],
  "requiredFieldRules": [],
  "conditionalLogicRules": [],
  "isActive": true,
  "createdById": "1a2b3c4d-...",
  "updatedById": null,
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T10:00:00.000Z"
}

Errors

CodeWhen
401Missing or invalid JWT

Update UTM rules

PUT /api/v1/utm-rules
Updates the workspace’s UTM rules. The rules record is created first if it does not exist, then updated. All body fields are optional.

Headers

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

Body

spaceCharacter
string
Character that replaces runs of whitespace in UTM values. Send an empty string to disable space replacement.
forceLowercase
boolean
When true, UTM values are lowercased during processing.
maxParameterLength
integer
Maximum value length. process truncates to this; validate flags an over-length value as an error.
allowedCharactersRegex
string
Regular expression a processed value must match. An invalid regex is skipped during validation.
prohibitedValues
string[]
Banned substrings. Matching is case-insensitive.
standardizationRules
object[]
Named standardization rules. See Standardization rules for the object shape. Persisted but not currently applied.
requiredFieldRules
object[]
Per-field validation rules. See Required field rules for the object shape.
conditionalLogicRules
object[]
If-then auto-set rules. See Conditional logic rules for the object shape.
isActive
boolean
Master switch. When false, validation and processing are bypassed.
update passes each field straight to the database. Sending a field with null or an empty value overwrites the stored value. Send only the fields you intend to change, and re-send array fields in full since they are replaced, not merged.

Example request

curl -X PUT https://api.linkutm.com/api/v1/utm-rules \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex" \
  -H "Content-Type: application/json" \
  -d '{
    "spaceCharacter": "-",
    "forceLowercase": true,
    "maxParameterLength": 80,
    "allowedCharactersRegex": "^[a-z0-9_-]+$",
    "prohibitedValues": ["test", "untitled"],
    "requiredFieldRules": [
      {
        "name": "Source required",
        "isActive": true,
        "description": "Source is required for all links",
        "validationType": "not_empty",
        "requiredParameters": ["source"]
      }
    ],
    "conditionalLogicRules": [
      {
        "ifField": "medium",
        "ifValue": "cpc",
        "condition": "equals",
        "thenSet": "source",
        "toValue": "google"
      }
    ],
    "isActive": true
  }'

Example response

{
  "id": "r-uuid",
  "workspaceId": "8a7b6c5d-...",
  "spaceCharacter": "-",
  "forceLowercase": true,
  "maxParameterLength": 80,
  "allowedCharactersRegex": "^[a-z0-9_-]+$",
  "prohibitedValues": ["test", "untitled"],
  "standardizationRules": [],
  "requiredFieldRules": [
    {
      "name": "Source required",
      "isActive": true,
      "description": "Source is required for all links",
      "validationType": "not_empty",
      "requiredParameters": ["source"]
    }
  ],
  "conditionalLogicRules": [
    {
      "ifField": "medium",
      "ifValue": "cpc",
      "condition": "equals",
      "thenSet": "source",
      "toValue": "google"
    }
  ],
  "isActive": true,
  "createdById": "1a2b3c4d-...",
  "updatedById": "1a2b3c4d-...",
  "createdAt": "2026-05-07T10:00:00.000Z",
  "updatedAt": "2026-05-07T11:00:00.000Z"
}

Errors

CodeWhen
401Missing or invalid JWT

Validate UTM parameters

POST /api/v1/utm-rules/validate
Runs a set of UTM values through the workspace rules and returns the validation result plus the normalized values. This endpoint does not save anything - use it to check a value before creating a link. When isActive is false, the response is valid: true with empty errors and warnings, and processedParams equal to the input.

Processing order

For each supplied parameter:
  1. Force lowercase (if forceLowercase).
  2. Replace whitespace with spaceCharacter (if set).
  3. Check against maxParameterLength - over-length adds an error.
  4. Check against prohibitedValues - a contained prohibited term adds an error.
  5. Check against allowedCharactersRegex - a non-matching value adds an error.
Then requiredFieldRules run against the processed values, and finally conditionalLogicRules run, which may auto-set fields and add warnings.

Headers

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

Body

The body is a flat object of parameter values. The standard keys are recognized, and any additional custom keys are also accepted and processed.
source
string
UTM source value.
medium
string
UTM medium value.
campaign
string
UTM campaign value.
term
string
UTM term value.
content
string
UTM content value.
Any extra string key beyond the five standard ones is processed the same way. Keys with undefined or null values are skipped.

Example request

curl -X POST https://api.linkutm.com/api/v1/utm-rules/validate \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "Google",
    "medium": "CPC",
    "campaign": "Q2 Launch"
  }'

Example response

{
  "valid": true,
  "errors": [],
  "warnings": [
    {
      "field": "source",
      "message": "Auto-set to \"google\" based on conditional rule"
    }
  ],
  "processedParams": {
    "source": "google",
    "medium": "cpc",
    "campaign": "q2-launch"
  }
}
An invalid example, where maxParameterLength is exceeded and a prohibited term is present:
{
  "valid": false,
  "errors": [
    {
      "field": "campaign",
      "message": "Value exceeds maximum length of 80 characters"
    },
    {
      "field": "source",
      "message": "Value contains prohibited term: \"test\""
    }
  ],
  "warnings": [],
  "processedParams": {
    "source": "test_source",
    "campaign": "..."
  }
}

Response fields

FieldTypeNotes
validbooleantrue when errors is empty.
errorsobject[]Each is { field, message }. A non-empty list means the values should not be saved.
warningsobject[]Each is { field, message }. Currently only emitted by conditional logic rules. Warnings do not make the result invalid.
processedParamsobjectThe normalized values, including any fields auto-set by conditional rules.

Errors

CodeWhen
401Missing or invalid JWT

Process a single value

POST /api/v1/utm-rules/process
Normalizes a single string against the workspace rules and returns both the original and the processed value. This applies only the normalization steps - lowercase, space replacement, and length truncation. It does not run prohibitedValues, allowedCharactersRegex, requiredFieldRules, or conditionalLogicRules. When isActive is false, the value is returned unchanged.

Headers

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

Body

value
string
required
The string to normalize.

Example request

curl -X POST https://api.linkutm.com/api/v1/utm-rules/process \
  -H "Authorization: Bearer $TOKEN" \
  -H "x-workspace-id: client-globex" \
  -H "Content-Type: application/json" \
  -d '{ "value": "Q2 Launch Campaign" }'

Example response

{
  "original": "Q2 Launch Campaign",
  "processed": "q2_launch_campaign"
}
Here forceLowercase lowercased the string and spaceCharacter (_) replaced the spaces. If the result were longer than maxParameterLength, it would also be truncated to that length.

Errors

CodeWhen
401Missing or invalid JWT