# Delete a preference

`DELETE /v1/preferences/{preference_id}`

Deletes a preference, returning its key to having no record, as if nothing had ever been stated. The deletion itself is kept on the key's history, so a later statement is still ordered against what was deleted.

**A statement the person made themselves cannot be deleted.** An unsubscribe or a stop keyword is their statement to reverse: it ends when they opt back in, and attempts to delete it return `422`. To restore messaging with the person's consent, record a `granted` statement with `consented_at` evidence instead; that records the change of mind rather than erasing the opt-out.

A delete is ordered like any statement, using the time it is received: if the record carries a statement made after that moment, the delete is refused and returned with `applied: false` alongside the surviving record. An ID that does not exist in the workspace returns `404`.

## Code samples

### TypeScript

```ts
const result = await bird.preferences.delete("prf_01krdgeqcxet5s7t44vh8rt9mg");
if (!result.applied) {
  console.log("refused — a newer statement survived:", result.preference?.status);
}
```

### Python

```py
result = client.preferences.delete("prf_01krdgeqcxet5s7t44vh8rt9mg")
if not result.applied and result.preference:
    print("refused, current statement:", result.preference.status)
```

### Go

```go
result, err := client.Preferences.Delete(context.Background(), "prf_01krdgeqcxet5s7t44vh8rt9mg")
if err != nil {
	log.Fatal(err)
}
// A newer statement recorded since refuses the delete: Applied comes back
// false and Preference carries the statement that survived.
switch {
case result.Applied == nil:
case !*result.Applied && result.Preference != nil:
	fmt.Println("delete refused, surviving statement:", result.Preference.Id)
default:
	fmt.Println("deleted")
}
```

### PHP

```php
// applied:false means a newer statement survived the request; the surviving
// record comes back on the result rather than being deleted out from under it.
$result = $bird->preferences->delete('prf_01krdgeqcxet5s7t44vh8rt9mg');
if ($result->getApplied() === false) {
    $survivor = $result->getPreference();
    echo 'refused: ', $survivor?->getStatus();
}
```

### CLI

```sh
bird preferences delete <preference-id> --yes
```

### cURL

```sh
curl -X DELETE "https://us1.platform.bird.com/v1/preferences/{preference_id}" \
  -H "Authorization: Bearer $TOKEN"
```

## Example response `200`

```json
{
  "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"
  }
}
```

## Path parameters

- `preference_id` (string): ID of the preference, as returned when it was recorded or listed. The ID stays stable while the key holds a record; deleting and re-recording the same key mints a new one.

## Response body

- `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.
- `preference.id` (string, required)
- `preference.channel` (string, required)
- `preference.handle` (string, required): 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, required): 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, required): 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, required)
- `preference.coverage` (string, required)
- `preference.effective_at` (string, required): 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, required)
- `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, required)
- `preference.updated_at` (string, required)