Skip to main content
A contact represents a person you might message — typically built from an email address, with an optional phone number for SMS. A list is a named group of contacts, useful for sending the same campaign to many people or for organizing audiences (e.g. “Newsletter subscribers”, “Beta testers”).

Contacts are optional for transactional sending

Send a message never requires a contact_id — you can pass to directly for one-off transactional messages like password resets or receipts. Create contacts when you want Pulsewave to track subscription state and unsubscribes on your behalf, which matters most for marketing or digest-style sends to a list.

Subscription state

Every contact has a subscribed boolean. It starts true and flips to false when:
  • The contact clicks an unsubscribe link in a message
  • The contact marks a message as spam (a message.complained event also fires)
  • You explicitly update the contact
Pulsewave automatically skips sending to unsubscribed contacts when you target a list, and fires a contact.unsubscribed event so you can mirror the state in your own database.
Unsubscribes are channel-wide. There’s no separate opt-out for email vs. SMS on the same contact — if you need independent consent per channel, model that with metadata and check it in your own application before sending.

Working with lists

# Create a list
curl -X POST https://api.pulsewave.dev/v1/lists \
  -H "Authorization: Bearer pw_live_..." \
  -d '{ "name": "Newsletter subscribers" }'

# Add a contact to it
curl -X POST https://api.pulsewave.dev/v1/lists/lst_7q1m4z/contacts \
  -H "Authorization: Bearer pw_live_..." \
  -d '{ "contact_id": "ct_5n2p9x" }'
A contact can belong to any number of lists. Deleting a list removes the grouping but does not delete the contacts in it; deleting a contact removes it from every list it belonged to.