Notifications
/v1/notificationsYour notifications, newest first — what happened and where it opens
curl -X GET https://api.tbbnetwork.com/v1/notifications \
-H "Authorization: Bearer <session access token>" \Response (200)
[
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "type",
"title": "title",
"body": null,
"href": null,
"readAt": "2026-07-01T12:00:00Z",
"createdAt": "2026-07-01T12:00:00Z"
}
]/v1/notifications/unread-countHow many of your notifications are unread
curl -X GET https://api.tbbnetwork.com/v1/notifications/unread-count \
-H "Authorization: Bearer <session access token>" \Response (200)
| Field | Type | Required |
|---|---|---|
| count | integer | — |
{
"count": 1
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/notifications/read-allMark all your notifications read
curl -X POST https://api.tbbnetwork.com/v1/notifications/read-all \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \Response (201)
| Field | Type | Required |
|---|---|---|
| count | integer | — |
{
"count": 1
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/notifications/{id}/readMark a notification read
curl -X POST https://api.tbbnetwork.com/v1/notifications/{id}/read \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \Parameters
| id | path | required |
Response (201)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| type | string | — |
| title | string | — |
| body | stringnull | — |
| href | stringnull | — |
| readAt | string,null (date-time) | — |
| createdAt | string (date-time) | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "type",
"title": "title",
"body": null,
"href": null,
"readAt": "2026-07-01T12:00:00Z",
"createdAt": "2026-07-01T12:00:00Z"
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/notifications/unsubscribePublic unsubscribe-center status (no auth) — pre-fills which categories an email is already opted out of. `token` (from an emailed unsubscribe link) only improves this prefill UX; without a valid one the form just shows nothing pre-ticked, since unsubscribe itself never requires one.
curl -X GET https://api.tbbnetwork.com/v1/notifications/unsubscribe \
-H "Authorization: Bearer sk_sandbox_..." \Parameters
| query | required | |
| token | query | optional |
Response (200)
| Field | Type | Required |
|---|---|---|
| optedOutCategories | string[] | — |
{
"optedOutCategories": [
"ACCOUNT"
]
}/v1/notifications/unsubscribeOpt an email out of the given categories (no auth — this is how every public unsubscribe link works, logged in or not). SECURITY mail can never be opted out of. Submitting an empty array re-subscribes to everything.
curl -X POST https://api.tbbnetwork.com/v1/notifications/unsubscribe \
-H "Authorization: Bearer sk_sandbox_..." \
-H "Idempotency-Key: 5f2f...b91" \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"categories": [
"ACCOUNT"
]
}'Request body
| Field | Type | Required |
|---|---|---|
| string (email) | yes | |
| categories | string[] | yes |
Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/notifications/preferencesThe authenticated, stronger override the public unsubscribe form doesn't expose — the caller's own email is resolved server-side from their principal, never client-supplied.
curl -X GET https://api.tbbnetwork.com/v1/notifications/preferences \
-H "Authorization: Bearer <session access token>" \Response (200)
| Field | Type | Required |
|---|---|---|
| stringnull | — | |
| allNonEssentialEmailOptOut | boolean | — |
| optedOutCategories | string[] | — |
{
"email": null,
"allNonEssentialEmailOptOut": false,
"optedOutCategories": [
"ACCOUNT"
]
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/notifications/preferencesSet the authenticated caller's own category opt-outs, plus the allNonEssentialEmailOptOut master switch (checked first, ahead of any per-category opt-out, and automatically covers a category added in the future).
curl -X PATCH https://api.tbbnetwork.com/v1/notifications/preferences \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \
-H "Content-Type: application/json" \
-d '{
"categories": [
"ACCOUNT"
],
"allNonEssentialEmailOptOut": false
}'Request body
| Field | Type | Required |
|---|---|---|
| categories | string[] | yes |
| allNonEssentialEmailOptOut | boolean | yes |
Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}