metadata, and subscribe status alongside an email address. Each project has its own address book. Drin stays transactional — there are no broadcasts or campaigns here — but a contact record is a convenient home for the data your own send logic reads.
Contacts vs suppressions. A contact’s
subscribed flag is your opt-in state — you decide what it means and whether to honour it before sending. Suppressions are enforced by Drin at send time and populated automatically by bounces and complaints. They’re separate systems; unsubscribing a contact does not suppress the address, and vice versa.Create a contact
POST /v1/contacts
Only email is required. firstName, lastName, subscribed (defaults to true), and an arbitrary metadata object are optional.
201 Contact
List & search
GET /v1/contacts
Cursor-paged like every list endpoint. Filter with subscribed=true|false and search names and email with q.
Update
PATCH /v1/contacts/{id}
Partial update — send only the fields you want to change. firstName and lastName accept null to clear them. To change subscribe state, use the dedicated endpoints below rather than patching it directly.
Unsubscribe & resubscribe
POST /v1/contacts/{id}/unsubscribe
Unsubscribing flips subscribed to false and stamps unsubscribedAt. Resubscribing flips it back and clears the timestamp. Both return the updated contact.
Delete
DELETE /v1/contacts/{id}
Permanently removes the contact record. Returns 204 No Content. This deletes the address-book entry only — it has no effect on already-sent messages or the suppression list.
cURL
Related
Suppressions
The enforced do-not-send list — separate from contact opt-out.
Send email
Read a contact, decide on
subscribed, then send.Contacts API
Every parameter and response schema for the contacts endpoints.
TypeScript SDK
The
drin.contacts resource and .paginate().