Notifications Endpoint
Notifications Endpoint
The POST /api/notify endpoint accepts a structured notification event and fans it out
to one or more configured external targets: a generic HTTP webhook, Sentry, and/or
Datadog. The response reports delivery success for each target independently so
callers can handle partial failures.
This endpoint does not require an Authorization header; it is protected via payload
validation, size limits, and rate limiting.
Request
POST /api/notify
Body
{ "event": "compilation.failed", // required — machine-readable event name "message": "Worker timed out", // required — human-readable description "level": "error", // optional — info | warn | error | debug (default: "info") "source": "bloqr-backend", // optional — originating service/component "timestamp": "2026-03-10T12:00:00Z", // optional — ISO 8601 (defaults to now) "metadata": { // optional — arbitrary key/value pairs "requestId": "req-abc123", "sourceCount": 5 }}| Field | Type | Required | Description |
|---|---|---|---|
event | string | ✅ | Machine-readable event identifier (e.g., compilation.failed) |
message | string | ✅ | Human-readable description of the event |
level | string | ❌ | Severity level: "info", "warn", "error", or "debug". Default: "info" |
source | string | ❌ | Originating service or component name |
timestamp | string | ❌ | ISO 8601 timestamp. Defaults to the time of the request |
metadata | object | ❌ | Arbitrary key/value pairs forwarded to all targets |
Responses
All targets delivered — 200
{ "success": true, "event": "compilation.completed", "deliveries": [ { "target": "generic", "success": true, "statusCode": 200 }, { "target": "sentry", "success": true, "statusCode": 200 } ], "duration": "42ms"}Partial failure — 200
The HTTP response is 200 even when some targets fail. Inspect deliveries to
determine which targets succeeded.
{ "success": true, "event": "compilation.completed", "deliveries": [ { "target": "generic", "success": false, "error": "Connection refused" }, { "target": "datadog", "success": true, "statusCode": 202 } ], "duration": "38ms"}All targets failed — 502
{ "success": false, "event": "compilation.completed", "deliveries": [ { "target": "generic", "success": false, "error": "Connection refused" } ], "duration": "15ms"}No targets configured — 503
{ "success": false, "error": "No notification targets are configured. Set WEBHOOK_URL, SENTRY_DSN, or DATADOG_API_KEY."}Target Configuration
Configure one or more of the following environment variables / Worker secrets.
The endpoint is a no-op (returns 503) when none are set.
| Variable | Type | Description |
|---|---|---|
WEBHOOK_URL | string | Generic HTTP webhook endpoint. Receives the raw request body as JSON via POST. |
SENTRY_DSN | string | Sentry DSN (https://<key>@<host>/<project>). Events are submitted to the Sentry Store API. |
DATADOG_API_KEY | string | Datadog API key. Events are submitted to the Datadog Events v1 API. |
Setting secrets
wrangler secret put WEBHOOK_URLwrangler secret put SENTRY_DSNwrangler secret put DATADOG_API_KEYTarget Behaviour
Generic webhook (WEBHOOK_URL)
The request body is forwarded verbatim as a JSON POST to WEBHOOK_URL. Use this for
Slack incoming webhooks, PagerDuty, or any custom HTTP endpoint.
Sentry (SENTRY_DSN)
The event is mapped to a Sentry store submission:
| Notify field | Sentry field |
|---|---|
message | message |
level (warn → warning) | level |
source | logger |
metadata | extra |
event | tags.event |
timestamp | timestamp |
Datadog (DATADOG_API_KEY)
The event is submitted to the Datadog Events v1 API (/api/v1/events):
| Notify field | Datadog field |
|---|---|
event | title |
message | text |
level | alert_type (warn → warning) |
source | source_type_name |
metadata keys | tags (key:value) |
timestamp | date_happened (Unix epoch) |
Examples
cURL
curl -X POST https://bloqr-backend.jk-com.workers.dev/api/notify \ -H "Content-Type: application/json" \ -d '{ "event": "compilation.completed", "message": "Compiled 12,500 rules from 5 sources", "level": "info", "source": "bloqr-backend", "metadata": { "ruleCount": 12500, "sourceCount": 5, "durationMs": 1240 } }'TypeScript
await fetch('/api/notify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ event: 'compilation.failed', message: 'Source download timed out after 30s', level: 'error', metadata: { sourceUrl: 'https://example.com/list.txt' }, }),});Notes
- Delivery to each target is attempted in parallel.
- Failed deliveries are reported in the response but do not affect other targets.
- The endpoint always returns
200when at least one target succeeds. Use thedeliveriesarray to detect partial failures.