Webhooks

Get told when links change, milestones are reached or conversions come in.

Webhooks need the Business plan, and the Administrator role or higher. Each event is posted as JSON, signed with the webhook's secret in the Blackgum-Signature header. The guide to receiving and checking events is at /docs/webhooks.

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.

OperationMethod and path
List webhooksGET /webhooks
Add a webhookPOST /webhooks
Get a webhookGET /webhooks/{webhookId}
Change a webhookPATCH /webhooks/{webhookId}
Remove a webhookDELETE /webhooks/{webhookId}
Replace the signing secretPOST /webhooks/{webhookId}/secret
Send a test eventPOST /webhooks/{webhookId}/test
List deliveriesGET /webhooks/{webhookId}/deliveries
Send a delivery againPOST /webhooks/{webhookId}/deliveries/{deliveryId}/resend

List webhooks

GET /webhooks

Lists the workspace's webhooks. Signing secrets are never shown again after they're created.

Full path
/api/v1/workspaces/{workspaceId}/webhooks
API key scope
webhooks:read
Role needed
Administrator or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks`, {
  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']}/webhooks",
    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": "hk7Qm2VfXa9R",
      "url": "https://example.com/hooks/blackgum",
      "description": "CRM sync",
      "format": "Json",
      "events": [
        "link.created",
        "link.click_threshold",
        "conversion.recorded"
      ],
      "clickThresholds": [
        100,
        1000
      ],
      "enabled": true,
      "disabledAt": null,
      "disabledReason": null,
      "consecutiveFailures": 0,
      "lastSuccessAt": "2026-10-15T01:12:09+00:00",
      "createdAt": "2026-10-14T23:40:00+00:00",
      "updatedAt": "2026-10-14T23:40:00+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.

Add a webhook

POST /webhooks

Adds a webhook and returns it with its signing secret. Store the secret now: it isn't shown again.

Full path
/api/v1/workspaces/{workspaceId}/webhooks
API key scope
webhooks:write
Role needed
Administrator or above
Plan
Needs webhooks in your plan (compare plans)

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.

Request body

JSON (Content-Type: application/json). Leave out fields you don't need.

NameTypeRequiredDescription
url string Yes Where to post events: a full https:// address on the public internet. For Slack, the incoming webhook address (https://hooks.slack.com/…); for Teams, the workflow or incoming webhook address.
format string No Json (default): the signed event, for your own code, Zapier or Make. Slack or Teams: a short message for a channel.
events string[] Yes Event types to send, such as ["link.created", "conversion.recorded"]. See the webhooks guide for the list.
clickThresholds integer[] No Click milestones for link.click_threshold, such as [100, 1000]: numbers of clicks from people, up to 10 of them.
description string No A note for yourself, up to 200 characters.
enabled boolean No false stops sending without removing the webhook. Default true.

Example request

curl

curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/hooks/blackgum",
  "description": "CRM sync",
  "events": [
    "link.created",
    "link.click_threshold",
    "conversion.recorded"
  ],
  "clickThresholds": [
    100,
    1000
  ]
}'

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "url": "https://example.com/hooks/blackgum",
    "description": "CRM sync",
    "events": [
      "link.created",
      "link.click_threshold",
      "conversion.recorded"
    ],
    "clickThresholds": [
      100,
      1000
    ]
  }),
});
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']}/webhooks",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    json={
        "url": "https://example.com/hooks/blackgum",
        "description": "CRM sync",
        "events": ["link.created", "link.click_threshold", "conversion.recorded"],
        "clickThresholds": [100, 1000],
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

201 Created · application/json

JSON

{
  "webhook": {
    "id": "hk7Qm2VfXa9R",
    "url": "https://example.com/hooks/blackgum",
    "description": "CRM sync",
    "format": "Json",
    "events": [
      "link.created",
      "link.click_threshold",
      "conversion.recorded"
    ],
    "clickThresholds": [
      100,
      1000
    ],
    "enabled": true,
    "disabledAt": null,
    "disabledReason": null,
    "consecutiveFailures": 0,
    "lastSuccessAt": "2026-10-15T01:12:09+00:00",
    "createdAt": "2026-10-14T23:40:00+00:00",
    "updatedAt": "2026-10-14T23:40:00+00:00"
  },
  "secret": "whsec_8yJ2kQ0w-LmV3pX9sT4rZbN6cF1aGhD5eU7iO2qWnYk"
}

Good to know

  • secret is null for Slack and Teams webhooks: those requests aren't signed.
  • A workspace can have up to 10 webhooks. One webhook can receive several event types.
  • Send a test event to check the address works before you rely on it.

Errors

StatusCodeMeaning
422webhook.url_requiredurl is missing.
422webhook.url_invalidurl isn't a full web address, or it includes a user name or password.
422webhook.url_httpsurl starts with http://.
422webhook.url_privateurl points at a local or private network address.
422webhook.url_not_slackformat is slack, but url isn't a Slack incoming webhook address.
422webhook.url_not_teamsformat is teams, but url isn't a Microsoft Teams webhook address.
422webhook.format_invalidformat isn't one of the allowed values.
422webhook.events_requiredevents is empty.
422webhook.event_unknownevents contains a name we don't send.
422webhook.threshold_invalidA click milestone isn't a whole number from 1 to 1,000,000,000.
422webhook.too_many_thresholdsMore than 10 click milestones.
422webhook.thresholds_requiredlink.click_threshold is chosen but there are no click milestones.
422webhook.description_too_longdescription is longer than 200 characters.
409webhook.limit_reachedThe workspace already has 10 webhooks.

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 webhook

GET /webhooks/{webhookId}

Returns one webhook, including whether it's failing or was turned off after failures.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}
API key scope
webhooks:read
Role needed
Administrator or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R`, {
  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']}/webhooks/hk7Qm2VfXa9R",
    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": "hk7Qm2VfXa9R",
  "url": "https://example.com/hooks/blackgum",
  "description": "CRM sync",
  "format": "Json",
  "events": [
    "link.created",
    "link.click_threshold",
    "conversion.recorded"
  ],
  "clickThresholds": [
    100,
    1000
  ],
  "enabled": true,
  "disabledAt": null,
  "disabledReason": null,
  "consecutiveFailures": 0,
  "lastSuccessAt": "2026-10-15T01:12:09+00:00",
  "createdAt": "2026-10-14T23:40:00+00:00",
  "updatedAt": "2026-10-14T23:40:00+00:00"
}

Good to know

  • consecutiveFailures counts failed attempts since the last success. disabledAt and disabledReason are set when we turned the webhook off because nothing got through for about a day.

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook 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 webhook

PATCH /webhooks/{webhookId}

Changes the fields you send and leaves the rest. Send enabled: true to turn a webhook back on after it was turned off.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}
API key scope
webhooks:write
Role needed
Administrator or above
Plan
Needs webhooks in your plan (compare plans)

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Request body

JSON (Content-Type: application/json). Leave out fields you don't need.

NameTypeRequiredDescription
url string No Where to post events: a full https:// address on the public internet. For Slack, the incoming webhook address (https://hooks.slack.com/…); for Teams, the workflow or incoming webhook address.
format string No Json (default): the signed event, for your own code, Zapier or Make. Slack or Teams: a short message for a channel.
events string[] No Event types to send, such as ["link.created", "conversion.recorded"]. See the webhooks guide for the list.
clickThresholds integer[] No Click milestones for link.click_threshold, such as [100, 1000]: numbers of clicks from people, up to 10 of them.
description string No A note for yourself, up to 200 characters.
enabled boolean No false stops sending without removing the webhook. Default true.

Example request

curl

curl -X PATCH "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true,
  "events": [
    "link.created",
    "link.deleted"
  ]
}'

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R`, {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "enabled": true,
    "events": [
      "link.created",
      "link.deleted"
    ]
  }),
});
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']}/webhooks/hk7Qm2VfXa9R",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    json={
        "enabled": True,
        "events": ["link.created", "link.deleted"],
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "id": "hk7Qm2VfXa9R",
  "url": "https://example.com/hooks/blackgum",
  "description": "CRM sync",
  "format": "Json",
  "events": [
    "link.created",
    "link.deleted"
  ],
  "clickThresholds": [
    100,
    1000
  ],
  "enabled": true,
  "disabledAt": null,
  "disabledReason": null,
  "consecutiveFailures": 0,
  "lastSuccessAt": "2026-10-15T01:12:09+00:00",
  "createdAt": "2026-10-14T23:40:00+00:00",
  "updatedAt": "2026-10-14T23:40:00+00:00"
}

Good to know

  • Turning a webhook back on clears its failure count. Events that happened while it was off aren't sent.

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook with that ID in this workspace.
422webhook.url_invalidurl isn't a full web address, or it includes a user name or password.
422webhook.url_httpsurl starts with http://.
422webhook.url_privateurl points at a local or private network address.
422webhook.url_not_slackformat is slack, but url isn't a Slack incoming webhook address.
422webhook.url_not_teamsformat is teams, but url isn't a Microsoft Teams webhook address.
422webhook.format_invalidformat isn't one of the allowed values.
422webhook.events_requiredevents is empty.
422webhook.event_unknownevents contains a name we don't send.
422webhook.threshold_invalidA click milestone isn't a whole number from 1 to 1,000,000,000.
422webhook.too_many_thresholdsMore than 10 click milestones.
422webhook.thresholds_requiredlink.click_threshold is chosen but there are no click milestones.
422webhook.description_too_longdescription 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.

Remove a webhook

DELETE /webhooks/{webhookId}

Removes the webhook and its delivery history. Events waiting to be sent to it are dropped.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}
API key scope
webhooks:write
Role needed
Administrator or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Example request

curl

curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R`, {
  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']}/webhooks/hk7Qm2VfXa9R",
    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

StatusCodeMeaning
404webhook.not_foundNo webhook 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.

Replace the signing secret

POST /webhooks/{webhookId}/secret

Makes a new signing secret and returns it once. The old secret stops working straight away, so update your receiver at the same time.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/secret
API key scope
webhooks:write
Role needed
Administrator or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Example request

curl

curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R/secret" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R/secret`, {
  method: "POST",
  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.post(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/webhooks/hk7Qm2VfXa9R/secret",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "webhook": {
    "id": "hk7Qm2VfXa9R",
    "url": "https://example.com/hooks/blackgum",
    "description": "CRM sync",
    "format": "Json",
    "events": [
      "link.created",
      "link.click_threshold",
      "conversion.recorded"
    ],
    "clickThresholds": [
      100,
      1000
    ],
    "enabled": true,
    "disabledAt": null,
    "disabledReason": null,
    "consecutiveFailures": 0,
    "lastSuccessAt": "2026-10-15T01:12:09+00:00",
    "createdAt": "2026-10-14T23:40:00+00:00",
    "updatedAt": "2026-10-14T23:40:00+00:00"
  },
  "secret": "whsec_Q2fN7mV0pX4sK9tR1zB6cL3aJ8hE5dU0yW2oI7gTnMk"
}

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook 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.

Send a test event

POST /webhooks/{webhookId}/test

Queues a ping event for this webhook. It's usually sent within a few seconds; check the result with List deliveries.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/test
API key scope
webhooks:write
Role needed
Administrator or above
Plan
Needs webhooks in your plan (compare plans)

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Example request

curl

curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R/test" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R/test`, {
  method: "POST",
  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.post(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/webhooks/hk7Qm2VfXa9R/test",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

202 · application/json

JSON

{
  "id": "dQ4nT8wLp2Zs",
  "eventId": "evt_3kQ9zV1mXw7TbR2aYpLc",
  "eventType": "ping",
  "state": "Pending",
  "attempts": 0,
  "statusCode": null,
  "durationMs": null,
  "error": null,
  "responseBody": null,
  "createdAt": "2026-10-15T01:12:08+00:00",
  "lastAttemptAt": null,
  "nextAttemptAt": "2026-10-15T01:12:08+00:00",
  "deliveredAt": null
}

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook with that ID in this workspace.
409webhook.disabledThe webhook is turned off, so it can't be sent a test or a repeat.

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.

List deliveries

GET /webhooks/{webhookId}/deliveries

Returns the webhook's last 50 deliveries, newest first, with the response we got back.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/deliveries
API key scope
webhooks:read
Role needed
Administrator or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R/deliveries" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R/deliveries`, {
  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']}/webhooks/hk7Qm2VfXa9R/deliveries",
    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": "dQ4nT8wLp2Zs",
      "eventId": "evt_3kQ9zV1mXw7TbR2aYpLc",
      "eventType": "link.created",
      "state": "Delivered",
      "attempts": 1,
      "statusCode": 200,
      "durationMs": 184,
      "error": null,
      "responseBody": "ok",
      "createdAt": "2026-10-15T01:12:08+00:00",
      "lastAttemptAt": "2026-10-15T01:12:09+00:00",
      "nextAttemptAt": null,
      "deliveredAt": "2026-10-15T01:12:09+00:00"
    }
  ]
}

Good to know

  • state is Pending (waiting for its first try or a retry), Delivered (your server answered with a 2xx status) or Failed (every retry failed, or the webhook was turned off first).
  • responseBody holds the first 2,000 characters of your server's answer. Deliveries are kept for 30 days.

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook 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.

Send a delivery again

POST /webhooks/{webhookId}/deliveries/{deliveryId}/resend

Queues the same event again, with the same event ID, as a new delivery. Useful after fixing your receiver.

Full path
/api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/deliveries/{deliveryId}/resend
API key scope
webhooks:write
Role needed
Administrator or above
Plan
Needs webhooks in your plan (compare plans)

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
webhookId string Yes The webhook's ID, as returned when it was created or listed.
deliveryId string Yes The delivery's ID, as returned when it was created or listed.

Example request

curl

curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/webhooks/hk7Qm2VfXa9R/deliveries/dQ4nT8wLp2Zs/resend" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/webhooks/hk7Qm2VfXa9R/deliveries/dQ4nT8wLp2Zs/resend`, {
  method: "POST",
  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.post(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/webhooks/hk7Qm2VfXa9R/deliveries/dQ4nT8wLp2Zs/resend",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

202 · application/json

JSON

{
  "id": "fR6uY1kM9cVb",
  "eventId": "evt_3kQ9zV1mXw7TbR2aYpLc",
  "eventType": "link.created",
  "state": "Pending",
  "attempts": 0,
  "statusCode": null,
  "durationMs": null,
  "error": null,
  "responseBody": null,
  "createdAt": "2026-10-15T01:12:08+00:00",
  "lastAttemptAt": null,
  "nextAttemptAt": "2026-10-15T02:00:00+00:00",
  "deliveredAt": null
}

Errors

StatusCodeMeaning
404webhook.not_foundNo webhook with that ID in this workspace.
404webhook.delivery_not_foundNo delivery with that ID for this webhook.
409webhook.disabledThe webhook is turned off, so it can't be sent a test or a repeat.

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.