# Update a WhatsApp keyword rule

`PATCH /v1/whatsapp/keyword-rules/{id}`

Changes the reply or the added keywords of a rule you created. Bird's own rules cannot be changed. To replace one, create a rule with the same operation and country and yours takes precedence.

What the rule applies to is fixed once created, so this changes the reply and the keywords only.

## Code samples

**TypeScript**

```ts
// Omitting keywords leaves the set alone; an empty array clears your additions
// back to Bird's. reply: null switches the auto-reply off and still records
// the opt-out.
const rule = await bird.whatsapp.keywordRules.update("wkr_01m2kj8x4te9p0rr7e5w2n1abc", {
  keywords: ["no more texts", "remove me"],
});
console.log(rule.effective_keywords);
```

Examples: [TypeScript](/docs/api/reference/update-whatsapp-keyword-rule.ts.md) · [Python](/docs/api/reference/update-whatsapp-keyword-rule.py.md) · [Go](/docs/api/reference/update-whatsapp-keyword-rule.go.md) · [PHP](/docs/api/reference/update-whatsapp-keyword-rule.php.md) · [CLI](/docs/api/reference/update-whatsapp-keyword-rule.cli.md) · [MCP](/docs/api/reference/update-whatsapp-keyword-rule.mcp.md) · [cURL](/docs/api/reference/update-whatsapp-keyword-rule.curl.md)

## Example response `200`

```json
{
  "id": "wkr_01krdgeqcxet5s7t44vh8rt9mg",
  "scope": "workspace",
  "operation": "opt_out",
  "country": "US",
  "waba": "102290129340398",
  "keywords": [
    "no more texts",
    "remove me"
  ],
  "effective_keywords": [
    "stop",
    "unsubscribe",
    "optout",
    "no more texts",
    "remove me"
  ],
  "reply": "You're off the list. ACME Courier won't message you again.",
  "created_at": "2026-09-15T10:04:00Z",
  "updated_at": "2026-09-15T10:04:00Z"
}
```

## Path parameters

- `id` (string): ID of the keyword rule, as returned by the list operation. Bird's own rules and yours share one ID space.

## Request body

- `keywords` (array of string): Replaces the extra keywords this rule matches, on top of the ones Bird ships. Send an empty array to keep Bird's keywords only. Omit to leave the current ones unchanged.
- `reply` (nullable string): Replaces the message sent back when a keyword matches. Set it to null to send nothing. Omit to leave it unchanged.

## Response body

- `id` (string, required)
- `scope` (string, required)

  Whether the rule is one Bird ships (`system`) or one your workspace created (`workspace`). Both kinds carry a `wkr_` ID and can be read; only a `workspace` rule can be changed or deleted. A `workspace` rule takes precedence over Bird's at the same grain, so it is how you replace a reply without losing the keywords Bird ships.

  Possible values: `system`, `workspace`
- `operation` (string, required)

  What Bird does when an inbound message matches the rule.

  - `opt_out` records that the sender no longer consents to receive any messages from your
    WhatsApp Business Account, including transactional ones. Typing the word is the person's
    own statement, so it covers everything, unlike WhatsApp's built-in marketing opt-out
    control, which stops marketing alone.
  - `opt_in` records that they consent again.

  A rule's operation is fixed once created, and a keyword belongs to exactly one operation, so
  a keyword Bird ships for `opt_out` cannot be reused for `opt_in`.

  This is an open enum. Accept unrecognized values: SMS already answers `help`, `info`, `confirm`
  and `custom`, and WhatsApp gains an operation without a new API version. Sending one Bird does
  not answer yet is refused with `E15082`.

  Possible values (may grow over time): `opt_in`, `opt_out`
- `country` (nullable string): The country the rule applies in, as an ISO 3166-1 alpha-2 code. It is the country of the person who messaged you, worked out from their phone number, not the country of the account they messaged. Null means the rule applies worldwide, which is what Bird's own rules do. A rule for a country outranks a worldwide rule for the people it covers.
- `waba` (nullable string): The WhatsApp Business Account the rule is limited to, identified by its WhatsApp-issued account ID, or null when it covers every account in your workspace. Bird's own rules are always null.
- `keywords` (array of string, required): The keywords this rule adds. For one of Bird's own rules this is the full set Bird ships. For a rule you created it is only what you added on top: it never restates or removes Bird's keywords, so `effective_keywords` is what actually matches.
- `effective_keywords` (array of string, required)

  Every keyword that matches this rule: Bird's keywords for the same operation and country, plus the ones you added. This is what an inbound message is compared against, and the whole message has to equal one of them. Keywords Bird adds later join it without you changing anything.
  For a rule of **yours** with no `country`, this list is not the whole set it matches: such a rule compares against Bird's keywords for the sender's country, which the list cannot show because it does not know who is writing, so it shows Bird's worldwide keywords instead. Which rule answers decides whether that matters. Yours with no `country` and no `waba` sits below Bird's own country rule, so a sender in a country Bird ships a rule for is answered by that rule and your reply is not used. Yours with a `waba` and no `country` sits above it, so those senders match that country's keywords and get your reply, which is more keywords than this list names. Set a `country` on your own rule to see and extend exactly the set those senders match. A `system` rule is unaffected: each matches only its own keywords, and the ladder checks Bird's country rules separately from its worldwide one.
- `reply` (nullable string): The message sent back when one of the keywords matches, or null when no reply is sent. The reply goes out on the conversation the inbound message opened.
- `created_at` (string, required): When the rule was created. On one of Bird's own rules this is when Bird last shipped a change to it.
- `updated_at` (string, required): When the rule was last changed. On one of Bird's own rules this is when Bird last shipped a change to it.

## Related resources

- [Should I use a Bird SDK or call the API directly?](/explained/platform/should-i-use-an-sdk-or-call-the-api-directly) (answer)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first email](/docs/get-started/send-your-first-email) (docs)

[Get an implementation brief](/learn/workspace?topic=api-basics)
