Sign inGet Started

Record a preference

POST
/v1/preferences
const result = await bird.preferences.create({
  channel: "sms",
  handle: "+15550001234",
  status: "revoked",
});
console.log(result.applied, result.preference?.id);
Response200
{
  "transition_id": "prt_01krdgeqcxet5s7t44vh8rt9mg",
  "preference": {
    "id": "prf_01krdgeqcxet5s7t44vh8rt9mg",
    "channel": "sms",
    "handle": "+15550001234",
    "sender_scope": "+15557654321",
    "topic_id": null,
    "status": "revoked",
    "coverage": "non_transactional",
    "origin": "api_key",
    "source": "signup-form-v2",
    "contact_id": "con_01krdgeqcxet5s7t44vh8rt9mg",
    "created_at": "2026-05-20T09:14:52Z",
    "updated_at": "2026-05-25T16:42:01Z"
  }
}

Records one statement, a grant or an opt-out, for a handle on one channel. Writing is an upsert: the key is the channel, handle, and optional sender scope, and a new statement replaces the key's current one.

Statements are ordered by when they were made, not when they arrive. A statement older than the key's current one is refused and returned with applied: false alongside the statement that survived; refusals are recorded on the key's history. Granting over a stored opt-out needs consented_at later than the opt-out, and a person's own opt-out (an unsubscribe, a stop keyword) cannot be overridden by a grant asserted on their behalf.

A 201 means this key had no record and one was created; a 200 returns the key's surviving record, whether this statement replaced it, repeated it, or was refused.

Request Payload

handle
string
required

Who the statement is about: an email address on the email channel, a phone number in E.164 format on SMS, WhatsApp, and Apple Messages for Business.

channel
string
required

The channel a preference statement applies to. A preference addresses one channel: the handle that identifies the person differs per channel, so opting out of one channel says nothing about the others. New channels can be added over time, so a value outside this list can be returned.

Possible values (may grow over time): email, sms, whatsapp, amb

status
string
required

What the statement says: granted records consent to receive messages, revoked records an opt-out. There is no third state: a person who never stated anything simply has no preference on record.

Possible values: granted, revoked

coverage
string

How much traffic the statement covers. Defaults to non_transactional, which keeps transactional messages such as receipts and verification codes flowing. Apple Messages for Business phone invitations have no transactional exemption, so either value covers them.

sender_scope
string

Limit the statement to one sender instead of the whole channel. On SMS this is the originator; on WhatsApp it identifies the business account; on Apple Messages for Business it is the Apple business ID used for invitations. Not supported on email, where preferences are always channel-wide.

source
string

Free-form note on where the statement came from: a form name, an import batch, a campaign. Stored verbatim and returned on the preference.

consented_at
string

When the person consented, on a granted statement. Required evidence when granting over a stored opt-out: the grant applies only if this is later than the opt-out it reverses. May not be in the future.

Response Payload

applied
boolean
required

Whether the request took effect. False only when it was refused as out of order; the surviving, newer statement is returned in preference.

transition_id
nullable string
required

Identifies this write on the key's record, for applied and refused requests alike. Null when the write was a repeat of the current statement and recorded nothing new.

preference
nullable object
required

The key's surviving statement. Null after an applied delete, when the key is back to having no record.

Show child attributes