Conversions
Report sign-ups, sales and other results for clicks on your links.
Conversion tracking needs the Business plan. Turn it on for a link (trackConversions), and the link adds a bgl_click value to the destination. Your server sends that value back here when the visitor signs up or buys. The guide to setting it up is at /docs/conversions.
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 |
|---|---|
| Record a conversion | POST /conversions |
Record a conversion
POST /conversions
Records that a click led to a sign-up, purchase or other event. Call it from your server, not the browser, so your API key stays private.
- Full path
/api/v1/workspaces/{workspaceId}/conversions- API key scope
-
conversions:write - Role needed
- Manager or above
- Plan
- Needs conversion tracking 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 |
|---|---|---|---|
click |
string | Yes | The bgl_click value the link added to your page's address, exactly as it arrived. |
event |
string | Yes | What happened, such as signup or purchase. Up to 64 characters. Use the same names every time: reports group by them. |
value |
number | No | How much it was worth, such as 49.95. Needs currency. |
currency |
string | No | Three-letter ISO 4217 code, such as AUD. Needed with value, and only with value. |
eventId |
string | No | Your own ID for this event, such as an order number, up to 200 characters. Sending the same eventId again returns the first record with 200 instead of counting it twice. |
occurredAt |
date-time | No | When it happened. Defaults to now. Must be after the click, within 90 days of it, and not in the future. |
Example request
curl
curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/conversions" \
-H "Authorization: Bearer $BGL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"click": "AQAAAAAAAAAqZxH3kQ8b2mVtPq7rWw",
"event": "purchase",
"value": 49.95,
"currency": "AUD",
"eventId": "order-1042"
}'
JavaScript
const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/conversions`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BGL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"click": "AQAAAAAAAAAqZxH3kQ8b2mVtPq7rWw",
"event": "purchase",
"value": 49.95,
"currency": "AUD",
"eventId": "order-1042"
}),
});
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']}/conversions",
headers={
"Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
},
json={
"click": "AQAAAAAAAAAqZxH3kQ8b2mVtPq7rWw",
"event": "purchase",
"value": 49.95,
"currency": "AUD",
"eventId": "order-1042",
},
timeout=30,
)
res.raise_for_status()
print(res.json())
Response
201 Created · application/json
JSON
{
"id": "Tq0nX4bVd2Lw",
"linkId": "ZiZihoWXe3as",
"event": "purchase",
"value": 49.95,
"currency": "AUD",
"eventId": "order-1042",
"clickAt": "2026-10-14T22:51:02+00:00",
"occurredAt": "2026-10-14T23:05:40.1834+00:00",
"createdAt": "2026-10-14T23:05:40.1834+00:00"
}
Good to know
- Returns 201 for a new conversion. If eventId was already used in this workspace, returns 200 with the conversion recorded first, so retries are safe.
- A conversion counts towards the link (and its campaign at the time of the click) if it happens within 90 days of the click.
- Click IDs are signed, so they can't be guessed or altered.
- Conversions appear in the analytics reports and the CSV export. See Analytics.
Errors
| Status | Code | Meaning |
|---|---|---|
| 422 | conversion.click_invalid | The click value isn't a bgl_click ID we issued, or it was changed. |
| 404 | conversion.click_not_found | The click ID is for a link in another workspace. |
| 422 | conversion.event_required | event is missing. |
| 422 | conversion.event_too_long | event is longer than 64 characters. |
| 422 | conversion.event_invalid | event contains control characters such as line breaks. |
| 422 | conversion.value_required | currency was sent without value. |
| 422 | conversion.currency_required | value was sent without currency. |
| 422 | conversion.currency_invalid | currency isn't a three-letter code. |
| 422 | conversion.value_too_large | value is too large to store. |
| 422 | conversion.event_id_too_long | eventId is longer than 200 characters. |
| 422 | conversion.in_future | occurredAt is in the future. |
| 422 | conversion.before_click | occurredAt is before the click happened. |
| 422 | conversion.outside_window | The conversion happened more than 90 days after the click, so it no longer counts towards the link. |
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.