Chart notes
Mark events such as a newsletter going out on the analytics charts.
A note has a date (and optionally a time) in the workspace's analytics time zone, and is for the whole workspace, one link or one campaign. Notes appear in the reports' notes list and as numbered flags on the charts in the app. Anyone who can see analytics can read them; Managers and above add, change and delete them.
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 notes | GET /notes |
| Add a note | POST /notes |
| Get a note | GET /notes/{noteId} |
| Change a note | PUT /notes/{noteId} |
| Delete a note | DELETE /notes/{noteId} |
List notes
GET /notes
Notes dated in the range, oldest first (up to 500).
- Full path
/api/v1/workspaces/{workspaceId}/notes- API key scope
-
analytics: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 |
|---|---|---|---|
from |
date | No | First day, as YYYY-MM-DD, in the report's time zone. Defaults to 29 days before to. |
to |
date | No | Last day, as YYYY-MM-DD. Defaults to today in the report's time zone. Future days are ignored. |
linkId |
string | No | Only notes shown for this link: its own, its campaign's and the workspace-wide ones. |
campaignId |
string | No | Only notes shown for this campaign: its own and the workspace-wide ones. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/notes?from=2026-10-01&to=2026-10-31" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/notes?from=2026-10-01&to=2026-10-31`, {
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']}/notes?from=2026-10-01&to=2026-10-31",
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": "nT4wq0Xbe2Lk",
"date": "2026-10-02",
"time": "09:30:00",
"text": "Spring newsletter sent",
"linkId": null,
"campaignId": "aiQrz1XgekFP",
"createdBy": "Sam Taylor",
"createdAt": "2026-10-02T00:14:51.4410+00:00",
"updatedAt": null
}
]
}
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.
Add a note
POST /notes
Adds a note to the charts.
- Full path
/api/v1/workspaces/{workspaceId}/notes- API key scope
-
analytics: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 |
|---|---|---|---|
date |
date | Yes | The day, as YYYY-MM-DD, in the workspace's time zone. |
time |
string | No | A 24-hour time that day, such as 09:30. |
text |
string | Yes | The note, up to 200 characters. |
linkId |
string | No | Show it for this link (and on the workspace's charts). |
campaignId |
string | No | Show it for this campaign (and on the workspace's charts). Not with linkId. |
Example request
curl
curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/notes" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"date": "2026-10-02",
"time": "09:30",
"text": "Spring newsletter sent",
"campaignId": "aiQrz1XgekFP"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/notes`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"date": "2026-10-02",
"time": "09:30",
"text": "Spring newsletter sent",
"campaignId": "aiQrz1XgekFP"
}),
});
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']}/notes",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"date": "2026-10-02",
"time": "09:30",
"text": "Spring newsletter sent",
"campaignId": "aiQrz1XgekFP",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
201 Created · application/json
JSON
{
"id": "nT4wq0Xbe2Lk",
"date": "2026-10-02",
"time": "09:30:00",
"text": "Spring newsletter sent",
"linkId": null,
"campaignId": "aiQrz1XgekFP",
"createdBy": "Sam Taylor",
"createdAt": "2026-10-02T00:14:51.4410+00:00",
"updatedAt": null
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | note.text_required | text is missing or blank. |
| 422 | note.text_too_long | text is longer than 200 characters. |
| 422 | note.date_required | date is missing. |
| 422 | note.date_invalid | date is before 2000 or after 2100. |
| 422 | note.time_invalid | time isn't a 24-hour time. |
| 422 | note.target_conflict | Both linkId and campaignId were sent. |
| 404 | link.not_found | No link with that ID in this workspace (or it was deleted). |
| 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.
Get a note
GET /notes/{noteId}
Returns one note.
- Full path
/api/v1/workspaces/{workspaceId}/notes/{noteId}- API key scope
-
analytics:read - Role needed
- Viewer or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
noteId |
string | Yes | The note's ID, as returned when it was created or listed. |
Example request
curl
curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/notes/nT4wq0Xbe2Lk" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/notes/nT4wq0Xbe2Lk`, {
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']}/notes/nT4wq0Xbe2Lk",
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": "nT4wq0Xbe2Lk",
"date": "2026-10-02",
"time": "09:30:00",
"text": "Spring newsletter sent",
"linkId": null,
"campaignId": "aiQrz1XgekFP",
"createdBy": "Sam Taylor",
"createdAt": "2026-10-02T00:14:51.4410+00:00",
"updatedAt": null
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | note.not_found | No note 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 note
PUT /notes/{noteId}
Replaces the note's date, time, text and what it's for. Leaving time, linkId or campaignId out removes it.
- Full path
/api/v1/workspaces/{workspaceId}/notes/{noteId}- API key scope
-
analytics:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
noteId |
string | Yes | The note'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 |
|---|---|---|---|
date |
date | Yes | The day, as YYYY-MM-DD. |
time |
string | No | A 24-hour time, such as 09:30. |
text |
string | Yes | Up to 200 characters. |
linkId |
string | No | Show it for this link. |
campaignId |
string | No | Show it for this campaign. |
Example request
curl
curl -X PUT "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/notes/nT4wq0Xbe2Lk" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"date": "2026-10-02",
"time": "10:00",
"text": "Spring newsletter sent (second batch)",
"campaignId": "aiQrz1XgekFP"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/notes/nT4wq0Xbe2Lk`, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"date": "2026-10-02",
"time": "10:00",
"text": "Spring newsletter sent (second batch)",
"campaignId": "aiQrz1XgekFP"
}),
});
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']}/notes/nT4wq0Xbe2Lk",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"date": "2026-10-02",
"time": "10:00",
"text": "Spring newsletter sent (second batch)",
"campaignId": "aiQrz1XgekFP",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
200 OK · application/json
JSON
{
"id": "nT4wq0Xbe2Lk",
"date": "2026-10-02",
"time": "10:00:00",
"text": "Spring newsletter sent (second batch)",
"linkId": null,
"campaignId": "aiQrz1XgekFP",
"createdBy": "Sam Taylor",
"createdAt": "2026-10-02T00:14:51.4410+00:00",
"updatedAt": "2026-10-03T22:40:12.0021+00:00"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | note.not_found | No note with that ID in this workspace. |
| 422 | note.text_required | text is missing or blank. |
| 422 | note.text_too_long | text is longer than 200 characters. |
| 422 | note.date_required | date is missing. |
| 422 | note.date_invalid | date is before 2000 or after 2100. |
| 422 | note.time_invalid | time isn't a 24-hour time. |
| 422 | note.target_conflict | Both linkId and campaignId were sent. |
| 404 | link.not_found | No link with that ID in this workspace (or it was deleted). |
| 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.
Delete a note
DELETE /notes/{noteId}
Deletes the note.
- Full path
/api/v1/workspaces/{workspaceId}/notes/{noteId}- API key scope
-
analytics:write - Role needed
- Manager or above
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | Your workspace ID, from Settings → Workspace. |
noteId |
string | Yes | The note's ID, as returned when it was created or listed. |
Example request
curl
curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/notes/nT4wq0Xbe2Lk" \
-H "Authorization: Bearer $BGL_API_KEY"
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/notes/nT4wq0Xbe2Lk`, {
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']}/notes/nT4wq0Xbe2Lk",
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 | note.not_found | No note 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.