Campaigns
Group links into campaigns that add UTM tags to every destination.
Campaigns need the Pro plan or above. Add a link to a campaign with campaignId when you create or change it.
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 campaigns | GET /campaigns |
| Create a campaign | POST /campaigns |
| Get a campaign | GET /campaigns/{campaignId} |
| Change a campaign | PUT /campaigns/{campaignId} |
| Archive a campaign | DELETE /campaigns/{campaignId} |
List campaigns
GET /campaigns
Lists campaigns, newest first (up to 500), with how many links each has and their clicks from people in the last 30 days.
- Full path
/api/v1/workspaces/{workspaceId}/campaigns- 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. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
includeArchived |
boolean | No | true includes archived campaigns. Default false. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/campaigns" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/campaigns`, {
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']}/campaigns",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
{
"items": [
{
"id": "aiQrz1XgekFP",
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026",
"linkCount": 12,
"humanClicks30Days": 431,
"createdAt": "2026-10-14T22:49:33.6455044+00:00",
"archived": false
}
]
}
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.
Create a campaign
POST /campaigns
Creates a campaign. Its UTM values are added to the destination of every link in it, unless the destination already sets them.
- Full path
/api/v1/workspaces/{workspaceId}/campaigns- API key scope
-
campaigns:write - Role needed
- Manager or above
- Plan
- Needs campaigns in your plan (compare plans)
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 200 characters. |
utmSource |
string | No | Value for utm_source, e.g. newsletter. Up to 200 characters. |
utmMedium |
string | No | Value for utm_medium, e.g. email. |
utmCampaign |
string | No | Value for utm_campaign, e.g. spring-2026. |
Example request
curl
curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/campaigns" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/campaigns`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026"
}),
});
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']}/campaigns",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
201 Created · application/json
JSON
{
"id": "aiQrz1XgekFP",
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026",
"linkCount": 0,
"humanClicks30Days": 0,
"createdAt": "2026-10-14T22:49:33.6455044+00:00",
"archived": false
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | campaign.name_required | The campaign has no name. |
| 422 | campaign.name_too_long | The name is longer than 200 characters. |
| 422 | campaign.utm_too_long | A UTM value 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.
Get a campaign
GET /campaigns/{campaignId}
Returns one campaign, archived or not.
- Full path
/api/v1/workspaces/{workspaceId}/campaigns/{campaignId}- 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. |
campaignId |
string | Yes | The campaign's ID, as returned when it was created or listed. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/campaigns/aiQrz1XgekFP" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/campaigns/aiQrz1XgekFP`, {
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']}/campaigns/aiQrz1XgekFP",
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": "aiQrz1XgekFP",
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026",
"linkCount": 12,
"humanClicks30Days": 431,
"createdAt": "2026-10-14T22:49:33.6455044+00:00",
"archived": false
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | campaign.not_found | No campaign with that ID in this workspace. When you add a link to a campaign, an archived one counts as missing. |
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 campaign
PUT /campaigns/{campaignId}
Replaces the campaign's name and UTM values. Leaving a UTM value out removes it. Links in the campaign use the new values straight away.
- Full path
/api/v1/workspaces/{workspaceId}/campaigns/{campaignId}- API key scope
-
campaigns:write - Role needed
- Manager or above
- Plan
- Needs campaigns in your plan (compare plans)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
campaignId |
string | Yes | The campaign'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 | Yes | Up to 200 characters. |
utmSource |
string | No | Value for utm_source. |
utmMedium |
string | No | Value for utm_medium. |
utmCampaign |
string | No | Value for utm_campaign. |
Example request
curl
curl -X PUT "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/campaigns/aiQrz1XgekFP" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026-extended"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/campaigns/aiQrz1XgekFP`, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026-extended"
}),
});
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.put(
f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/campaigns/aiQrz1XgekFP",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026-extended",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
{
"id": "aiQrz1XgekFP",
"name": "Spring sale",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "spring-2026-extended",
"linkCount": 12,
"humanClicks30Days": 431,
"createdAt": "2026-10-14T22:49:33.6455044+00:00",
"archived": false
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | campaign.not_found | No campaign with that ID in this workspace. When you add a link to a campaign, an archived one counts as missing. |
| 422 | campaign.name_required | The campaign has no name. |
| 422 | campaign.name_too_long | The name is longer than 200 characters. |
| 422 | campaign.utm_too_long | A UTM value 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.
Archive a campaign
DELETE /campaigns/{campaignId}
Archives the campaign. Its links keep working and keep their UTM tags; new links can't be added to it.
- Full path
/api/v1/workspaces/{workspaceId}/campaigns/{campaignId}- API key scope
-
campaigns:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
campaignId |
string | Yes | The campaign's ID, as returned when it was created or listed. |
Example request
curl
curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/campaigns/aiQrz1XgekFP" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/campaigns/aiQrz1XgekFP`, {
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']}/campaigns/aiQrz1XgekFP",
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 | campaign.not_found | No campaign with that ID in this workspace. When you add a link to a campaign, an archived one counts as missing. |
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.