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);result = client.preferences.create(
channel="email",
handle="jane@acme.com",
status="granted",
consented_at="2026-08-20T14:03:10Z",
source="signup-form-v2",
)
if result.preference:
print(result.applied, result.preference.id)result, err := client.Preferences.Create(context.Background(), bird.PreferencesCreateParams{
Channel: bird.PreferenceChannelEmail,
Handle: "recipient@example.com",
Status: bird.PreferenceStatusGranted,
Source: "signup-form-v2",
ConsentedAt: time.Now(),
})
if err != nil {
log.Fatal(err)
}
// A newer statement already on file answers Applied false instead of an
// error, with the surviving statement in Preference.
if result.Applied != nil && *result.Applied {
fmt.Println("grant recorded")
}$result = $bird->preferences->create(
channel: 'email',
handle: 'jane@acme.com',
status: 'granted',
source: 'signup-form-v2',
consentedAt: new DateTimeImmutable('2026-08-20T14:03:10Z'),
);
echo var_export($result->getApplied(), true);bird preferences create \
--channel sms \
--coverage non_transactional \
--handle +15550001234 \
--status revokedcurl -X POST "https://us1.platform.bird.com/v1/preferences" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"channel": "sms",
"handle": "+15550001234",
"status": "revoked",
"coverage": "non_transactional"
}'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
आवश्यक
Who the statement is about: an email address on the email channel, a phone number in E.164 format on SMS and WhatsApp.
channel
string
आवश्यक
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
status
string
आवश्यक
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.
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. 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
आवश्यक
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
आवश्यक
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
आवश्यक
The key's surviving statement. Null after an applied delete, when the key is back to having no record.
चाइल्ड एट्रिब्यूट दिखाएँ
preference.id
string
आवश्यक
preference.channel
string
आवश्यक
preference.handle
string
आवश्यक
Who the statement is about: an email address on the email channel, a phone number in E.164 format on SMS and WhatsApp.
preference.sender_scope
nullable string
आवश्यक
The sender the statement is limited to, or null when it covers the whole channel. On SMS this is the originator the person replied to; on WhatsApp it identifies the business account that messaged them. Email preferences are always channel-wide, so it is always null there.
preference.topic_id
nullable string
आवश्यक
The topic the statement is limited to, or null when it covers every topic. Part of the key that identifies a statement, alongside sender_scope.
preference.status
string
आवश्यक
preference.coverage
string
आवश्यक
preference.effective_at
string
आवश्यक
When the statement was made, as reported by whoever made it. This is what orders one key's statements: a write dated before this moment is refused rather than applied.
preference.origin
string
आवश्यक
preference.source
nullable string
Free-form note on where the statement came from, as supplied when it was recorded: a form name, an import batch, a campaign. Null when none was given.
preference.consented_at
nullable string
When the person consented, as evidenced by whoever asserted the grant. Null on statements that carry no consent evidence, including every opt-out.
preference.contact_id
nullable string
The contact whose handle matched when the statement was recorded. Null when no contact matched at that moment; it is not updated when contacts change later.
preference.created_at
string
आवश्यक
preference.updated_at
string
आवश्यक