Sendry Docs
API Reference

Topics

Manage subscription topics and the contacts subscribed to them.

Topics are named subscription categories, such as product-updates or security-alerts. When a topic has opt_in_required set to true, only contacts who explicitly subscribed receive emails for it; otherwise emails go to everyone except those who unsubscribed.


List topics

GET /v1/topics

Requires read_only scope.

Query parameters

ParameterTypeDefaultDescription
limitnumber50Results per page (max 100).
cursorstringPagination cursor from the previous response's next_cursor.

Response

{
  "data": [
    {
      "id": "top_abc123",
      "name": "product-updates",
      "description": "Product feature announcements and release notes",
      "opt_in_required": true,
      "created_at": "2025-03-12T09:00:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Create a topic

POST /v1/topics

Requires full_access scope. Topic names are unique per organization; reusing an existing name returns 409 with code topic_name_taken.

Request body

FieldTypeRequiredDescription
namestringYesTopic name, unique per org (1-200 characters).
descriptionstringNoHuman-readable description of the topic.
opt_in_requiredbooleanNoIf true, only explicit subscribers receive the topic. Defaults to false.

Example request

{
  "name": "product-updates",
  "description": "Product feature announcements and release notes",
  "opt_in_required": true
}

Response

{
  "id": "top_abc123",
  "name": "product-updates",
  "description": "Product feature announcements and release notes",
  "opt_in_required": true,
  "created_at": "2025-03-12T09:00:00Z"
}

Get a topic

GET /v1/topics/:id

Requires read_only scope.

Response

{
  "id": "top_abc123",
  "name": "product-updates",
  "description": "Product feature announcements and release notes",
  "opt_in_required": true,
  "created_at": "2025-03-12T09:00:00Z"
}

Delete a topic

DELETE /v1/topics/:id

Requires full_access scope.

Response

{
  "deleted": true
}

Subscribe a contact to a topic

POST /v1/topics/:id/subscribe

Requires full_access scope. The contact must already exist in the organization, matched by email; otherwise the request returns 404 with code contact_not_found.

Request body

FieldTypeRequiredDescription
emailstringYesEmail of the contact to subscribe.

Example request

{
  "email": "jane@example.com"
}

Response

{
  "contact_id": "ct_abc123",
  "topic_id": "top_abc123",
  "subscribed": true
}

Unsubscribe a contact from a topic

POST /v1/topics/:id/unsubscribe

Requires full_access scope. The contact must already exist in the organization, matched by email.

Request body

FieldTypeRequiredDescription
emailstringYesEmail of the contact to unsubscribe.

Example request

{
  "email": "jane@example.com"
}

Response

{
  "contact_id": "ct_abc123",
  "topic_id": "top_abc123",
  "subscribed": false
}

List subscribers for a topic

GET /v1/topics/:id/subscribers

Requires read_only scope. Returns all subscription records for the topic, including unsubscribed contacts, ordered by updated_at descending.

Query parameters

ParameterTypeDefaultDescription
limitnumber50Results per page (max 100).
cursorstringPagination cursor from the previous response's next_cursor.

Response

{
  "data": [
    {
      "contact_id": "ct_abc123",
      "email": "jane@example.com",
      "subscribed": true,
      "updated_at": "2025-03-12T09:00:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

On this page