Skip to content

Managing your audience

Your audience — who you can notify and where to reach them — is managed over the tenant-scoped REST API.

ActionEndpoint
Identify / upsert a subscriberPUT /v1/subscribers/:externalId
Delete a subscriberDELETE /v1/subscribers/:externalId
Subscribe to a topicPUT /v1/subscribers/:externalId/subscriptions/:topicKey
UnsubscribeDELETE /v1/subscribers/:externalId/subscriptions/:topicKey
Create / update a topicPUT /v1/topics/:key
Delete a topicDELETE /v1/topics/:key

:externalId is your user id — palumb never mints subscriber ids.

PUT /v1/subscribers/:externalId creates or updates a subscriber. It’s idempotent, so call it whenever your user’s contact details change:

Terminal window
curl -sS -X PUT http://localhost:3000/v1/subscribers/cust_1 \
-H "Authorization: Bearer $PALUMB_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "contacts": { "email": ["cust1@example.com"] },
"locale": "en",
"attributes": { "plan": "pro" } }'

contacts is a per-kind map, and the upsert merges it kind by kind:

You sendResult for that kind
A non-empty listOverwrites the addresses
An empty list []Clears the kind
Omit the kindSurvives unchanged

So adding a phone number doesn’t disturb an existing email:

Terminal window
curl -sS -X PUT http://localhost:3000/v1/subscribers/cust_1 \
-H "Authorization: Bearer $PALUMB_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "contacts": { "sms": ["+391234567"] } }' # email kept; sms added

locale and attributes follow the same “provided overwrites, omitted keeps” rule. The contacts kinds line up with channel kinds — delivery reads the address from contacts[kind].

A topic groups subscribers so a single trigger can fan out to all of them. You can create one explicitly:

Terminal window
curl -sS -X PUT http://localhost:3000/v1/topics/oncall \
-H "Authorization: Bearer $PALUMB_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "name": "On-call engineers" }'

…or just subscribe someone — the topic is created implicitly on first subscribe if it doesn’t exist yet (an implicit create never clobbers a name you set explicitly):

Terminal window
curl -sS -X PUT http://localhost:3000/v1/subscribers/cust_1/subscriptions/oncall \
-H "Authorization: Bearer $PALUMB_API_KEY"

Re-subscribing is a no-op (the subscriber↔topic pair is unique). Unsubscribe with the matching DELETE. A topic trigger then expands the topic to its subscribers, deduplicated, and starts one run each.

  • Delete a subscriber — removes its subscriptions too (database-level cascade):

    Terminal window
    curl -sS -X DELETE http://localhost:3000/v1/subscribers/cust_1 \
    -H "Authorization: Bearer $PALUMB_API_KEY"
  • Delete a topicguarded. If any subscriber is still on it, the delete is rejected with 409; unsubscribe everyone first. This keeps you from silently orphaning subscriptions.

    Terminal window
    curl -sS -X DELETE http://localhost:3000/v1/topics/oncall \
    -H "Authorization: Bearer $PALUMB_API_KEY"
  • Audience — the concept behind these endpoints.
  • Triggers — targeting subscribers and topics.
  • REST API — the full endpoint list.