Skip to content
On this site

Topics

The categories contacts subscribe to. A broadcast scoped to a topic reaches only the contacts opted in to it, and the hosted preference page is where they choose.

How a topic decides

  • Each contact has an effective subscription to every topic: their own choice where one was recorded, and the topic's default_subscription otherwise. A broadcast with a topic_id goes only to contacts whose effective subscription is opt_in.
  • default_subscription is fixed at creation. Changing it would silently flip everyone who never chose, so the API refuses rather than asking you to be careful.
  • A public topic is listed on every contact's preference page. A private one appears only for contacts already opted in — for a list people join somewhere else and should be able to leave here.
  • A global unsubscribe wins over every topic: a contact with unsubscribed: true receives nothing, whatever their choices say.

Consent

Every choice — from the API, an import, the preference page or a one-click unsubscribe — writes a consent record with its source, time and, where there was one, the IP address and user agent. Records are kept for three years and survive the contact's erasure with a hash of the address, which is what lets an opt-out be proven later.

Endpoints

POST /topics

A category contacts subscribe to, with a default for those who never chose.

Body

Body
FieldTypeDescription
name*stringUp to 50 characters, unique among live topics.
default_subscription*stringopt_in or opt_out: what a contact with no explicit choice is treated as. Fixed after creation.
descriptionstringUp to 200 characters, shown on the preference page.
visibilitystringpublic lists the topic on every contact's preference page; private (the default) only for contacts already opted in.
curl -X POST "https://api.rasket.com/topics" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Product updates",
  "description": "What shipped this month.",
  "default_subscription": "opt_in",
  "visibility": "public"
}'

Response 201

{
  "object": "topic",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
  • A live topic with the same name is 422 invalid_parameter.
  • A broadcast scoped to a topic goes only to contacts whose effective subscription to it is opt_in.

GET /topics

Every live topic, newest first.

Query parameters

Query parameters
FieldTypeDescription
limitintegerHow many items to return, 1–100. Defaults to 20.
afterstringReturn the page that follows this item ID. Mutually exclusive with before.
beforestringReturn the page that precedes this item ID. Mutually exclusive with after.
curl -X GET "https://api.rasket.com/topics" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
      "name": "Product updates",
      "description": "What shipped this month.",
      "default_subscription": "opt_in",
      "visibility": "public",
      "created_at": "2026-09-08T22:22:17.595Z"
    }
  ]
}

GET /topics/{id}

One topic by ID.

Path parameters

Path parameters
FieldTypeDescription
id*stringThe topic's ID.
curl -X GET "https://api.rasket.com/topics/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "topic",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "name": "Product updates",
  "description": "What shipped this month.",
  "default_subscription": "opt_in",
  "visibility": "public",
  "created_at": "2026-09-08T22:22:17.595Z"
}

PATCH /topics/{id}

Change the name, description or visibility.

Path parameters

Path parameters
FieldTypeDescription
id*stringThe topic's ID.

Body

Body
FieldTypeDescription
namestringUp to 50 characters.
descriptionstring | nullnull clears it.
visibilitystringpublic or private.
curl -X PATCH "https://api.rasket.com/topics/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "visibility": "private"
}'

Response 200

{
  "object": "topic",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
  • default_subscription cannot change: a body that carries it is 422 invalid_parameter. Changing it would silently resubscribe or unsubscribe everyone who never chose.

DELETE /topics/{id}

Retire the topic and free its name.

Path parameters

Path parameters
FieldTypeDescription
id*stringThe topic's ID.
curl -X DELETE "https://api.rasket.com/topics/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "topic",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "deleted": true
}
  • The topic is 404 from that moment. Emails and consent records that name it keep doing so.