UTM templates
Save sets of UTM tags to reuse when creating links.
A UTM template is a name and up to five UTM tags (utm_source, utm_medium, utm_campaign, utm_term and utm_content), shared by everyone in the workspace. The app offers them when creating a link and adds the tags to the destination address. Through the API, read a template and add its tags to destinationUrl yourself. Saving, changing and deleting templates needs permission to edit links.
Every path below starts with https://bgum.me/api/v1/workspaces/{workspaceId}. Send your API key in the Authorization header as described in the API overview.
| Operation | Method and path |
|---|---|
| List UTM templates | GET /utm-templates |
| Save a UTM template | POST /utm-templates |
| Get a UTM template | GET /utm-templates/{templateId} |
| Change a UTM template | PATCH /utm-templates/{templateId} |
| Delete a UTM template | DELETE /utm-templates/{templateId} |
List UTM templates
GET /utm-templates
Lists the workspace's UTM templates by name.
- Full path
/api/v1/workspaces/{workspaceId}/utm-templates- API key scope
-
links:read - Role needed
- Viewer or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/utm-templates" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/utm-templates`, {
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);
Python
import os
import requests
res = requests.get(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/utm-templates",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
[
{
"id": "Ut3kWm8sQa1z",
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly",
"utmTerm": null,
"utmContent": null,
"createdAt": "2026-10-16T04:10:22.4417+00:00"
}
]
Errors
Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.
Save a UTM template
POST /utm-templates
Saves a template. Up to 100 per workspace, each with a different name.
- Full path
/api/v1/workspaces/{workspaceId}/utm-templates- API key scope
-
links:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
Request body
JSON (Content-Type: application/json). Leave out fields you don't need.
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Up to 100 characters, different from the workspace's other templates (case doesn't matter). |
utmSource |
string | No | utm_source, up to 200 characters. |
utmMedium |
string | No | utm_medium, up to 200 characters. |
utmCampaign |
string | No | utm_campaign, up to 200 characters. |
utmTerm |
string | No | utm_term, up to 200 characters. |
utmContent |
string | No | utm_content, up to 200 characters. |
Example request
curl
curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/utm-templates" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/utm-templates`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly"
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);
Python
import os
import requests
res = requests.post(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/utm-templates",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
201 Created · application/json
JSON
{
"id": "Ut3kWm8sQa1z",
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly",
"utmTerm": null,
"utmContent": null,
"createdAt": "2026-10-16T04:10:22.4417+00:00"
}
Good to know
- At least one tag is needed. Spaces at either end are removed.
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | utm_template.name_required | The template has no name. |
| 422 | utm_template.name_too_long | The name is longer than 100 characters. |
| 409 | utm_template.name_taken | Another template in the workspace already has that name (case doesn't matter). |
| 422 | utm_template.empty | Every UTM tag is empty. |
| 422 | utm_template.value_too_long | A UTM tag is longer than 200 characters. |
| 409 | utm_template.too_many | The workspace already has 100 UTM templates. |
Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.
Get a UTM template
GET /utm-templates/{templateId}
Returns one template.
- Full path
/api/v1/workspaces/{workspaceId}/utm-templates/{templateId}- API key scope
-
links:read - Role needed
- Viewer or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
templateId |
string | Yes | The UTM template's ID, as returned when it was created or listed. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/utm-templates/Ut3kWm8sQa1z" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/utm-templates/Ut3kWm8sQa1z`, {
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);
Python
import os
import requests
res = requests.get(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/utm-templates/Ut3kWm8sQa1z",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
{
"id": "Ut3kWm8sQa1z",
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "monthly",
"utmTerm": null,
"utmContent": null,
"createdAt": "2026-10-16T04:10:22.4417+00:00"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | utm_template.not_found | No UTM template with that ID in this workspace. |
Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.
Change a UTM template
PATCH /utm-templates/{templateId}
Changes only the fields you send. Send an empty string to remove a tag.
- Full path
/api/v1/workspaces/{workspaceId}/utm-templates/{templateId}- API key scope
-
links:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
templateId |
string | Yes | The UTM template's ID, as returned when it was created or listed. |
Request body
JSON (Content-Type: application/json). Leave out fields you don't need.
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | No | New name. |
utmSource |
string | No | New utm_source. |
utmMedium |
string | No | New utm_medium. |
utmCampaign |
string | No | New utm_campaign. |
utmTerm |
string | No | New utm_term. |
utmContent |
string | No | New utm_content. |
Example request
curl
curl -X PATCH "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/utm-templates/Ut3kWm8sQa1z" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"utmCampaign": "november",
"utmContent": ""
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/utm-templates/Ut3kWm8sQa1z`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"utmCampaign": "november",
"utmContent": ""
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);
Python
import os
import requests
res = requests.patch(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/utm-templates/Ut3kWm8sQa1z",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"utmCampaign": "november",
"utmContent": "",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
{
"id": "Ut3kWm8sQa1z",
"name": "Monthly newsletter",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "november",
"utmTerm": null,
"utmContent": null,
"createdAt": "2026-10-16T04:10:22.4417+00:00"
}
Good to know
- Links already made with the template keep their tags.
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | utm_template.not_found | No UTM template with that ID in this workspace. |
| 422 | utm_template.name_required | The template has no name. |
| 422 | utm_template.name_too_long | The name is longer than 100 characters. |
| 409 | utm_template.name_taken | Another template in the workspace already has that name (case doesn't matter). |
| 422 | utm_template.empty | Every UTM tag is empty. |
| 422 | utm_template.value_too_long | A UTM tag is longer than 200 characters. |
Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.
Delete a UTM template
DELETE /utm-templates/{templateId}
Deletes a template. Links made with it keep their tags.
- Full path
/api/v1/workspaces/{workspaceId}/utm-templates/{templateId}- API key scope
-
links:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
templateId |
string | Yes | The UTM template's ID, as returned when it was created or listed. |
Example request
curl
curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/utm-templates/Ut3kWm8sQa1z" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/utm-templates/Ut3kWm8sQa1z`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
// 204 No Content: nothing to read.
Python
import os
import requests
res = requests.delete(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/utm-templates/Ut3kWm8sQa1z",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
timeout=30,
)
res.raise_for_status()
# 204 No Content: nothing to read.
Response
204 No Content
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | utm_template.not_found | No UTM template with that ID in this workspace. |
Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.
Something missing or unclear? Tell us and we'll improve this page.