> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Send WhatsApp messages through Courier

> Send WhatsApp messages through Twilio with a pre-approved template.

export const Endpoint = ({method, path, name, href, children, bare}) => {
  const verb = String(method || "").toUpperCase();
  const title = verb + " " + path;
  const label = children || name || path;
  if (bare) {
    return href ? <a href={href}><code>{title}</code></a> : <code>{title}</code>;
  }
  if (!href) {
    return <span className="cx-endpoint" data-method={verb} title={title}>
        <span className="cx-endpoint-label">{label}</span>
        <span className="cx-endpoint-method">{verb}</span>
      </span>;
  }
  return <a className="cx-endpoint" data-method={verb} href={href} title={title}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">{verb}</span>
    </a>;
};

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</span>
    </a>;
};

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

Courier uses the [Twilio API for WhatsApp](https://twilio.com/whatsapp) as the delivery partner.

## Prerequisites

* [A Twilio account with WhatsApp enabled](https://www.twilio.com/)
* [Your Twilio Account SID and Auth Token](https://console.twilio.com/)
* A WhatsApp-enabled "From" number in Twilio

## Setup

<Steps>
  <Step title="Get your Twilio credentials">
    In Twilio, open the [console](https://console.twilio.com/) and copy your Account SID and Auth Token. Your WhatsApp sender is the "From" number.
  </Step>

  <Step title="Configure in Courier">
    Open the <AppLink href="https://app.courier.com/integrations/catalog/twilio-whatsapp">WhatsApp integration</AppLink> in Courier, enter your Twilio Account SID, Auth Token, and "From" number, then save.
  </Step>
</Steps>

## Profile requirements

WhatsApp addresses the recipient by phone number, so the profile you send to needs a `phone_number`. Store it once with <Endpoint method="POST" path="/profiles/{user_id}" name="Create a Profile" href="/docs/api-reference/user-profiles/create-a-profile" />, which merges into the profile and creates it if it does not exist:

<CodeGroup>
  ```javascript Node.js highlight={3} theme={null}
  const profile = await client.profiles.create('user_123', {
    profile: {
      phone_number: '+15551234567',
    },
  });
  ```

  ```python Python highlight={4} theme={null}
  profile = client.profiles.create(
      user_id="user_123",
      profile={
          "phone_number": "+15551234567",
      },
  )
  ```

  ```bash cURL highlight={7} theme={null}
  curl --request POST \
    --url https://api.courier.com/profiles/user_123 \
    --header "Authorization: Bearer $COURIER_API_KEY" \
    --header 'Content-Type: application/json' \
    --data '{
      "profile": {
        "phone_number": "+15551234567"
      }
    }'
  ```

  ```ruby Ruby highlight={4} theme={null}
  profile = courier.profiles.create(
    "user_123",
    profile: {
      phone_number: "+15551234567"
    }
  )
  ```

  ```go Go highlight={6} theme={null}
  profile, err := client.Profiles.New(
  	context.TODO(),
  	"user_123",
  	courier.ProfileNewParams{
  		Profile: map[string]any{
  			"phone_number": "+15551234567",
  		},
  	},
  )
  ```

  ```java Java highlight={4} theme={null}
  ProfileCreateParams params = ProfileCreateParams.builder()
      .userId("user_123")
      .profile(ProfileCreateParams.Profile.builder()
          .putAdditionalProperty("phone_number", JsonValue.from("+15551234567"))
          .build())
      .build();
  ProfileCreateResponse profile = client.profiles().create(params);
  ```

  ```php PHP highlight={2} theme={null}
  $profile = $client->profiles->create('user_123', profile: [
    'phone_number' => '+15551234567',
  ]);
  ```

  ```csharp C# highlight={6} theme={null}
  ProfileCreateParams parameters = new()
  {
      UserID = "user_123",
      Profile = new Dictionary<string, JsonElement>()
      {
          { "phone_number", JsonSerializer.SerializeToElement("+15551234567") },
      },
  };
  var profile = await client.Profiles.Create(parameters);
  ```

  ```bash CLI highlight={4} theme={null}
  courier profiles create \
    --api-key "$COURIER_API_KEY" \
    --user-id user_123 \
    --profile '{"phone_number":"+15551234567"}'
  ```

  ```text MCP theme={null}
  With Courier MCP, create a profile for user_123 with the phone number +15551234567.
  ```
</CodeGroup>

Then send to `user_id` and Courier resolves the address.

For a one-off with no stored profile, pass it inline instead: `"to": { "phone_number": "+15551234567" }`.

<CardGroup cols={1}>
  <Card title="Send by user id" icon="user" href="/docs/recipients/overview#send-by-user-id">
    The call in every language, and the rest of the profile object.
  </Card>
</CardGroup>

## Send to a recipient

<Tabs>
  <Tab title="Send to user id">
    Courier reads `phone_number` off the saved profile, so preferences apply and the value can change without touching this code.

    <CodeGroup>
      ```javascript Node.js highlight={4} theme={null}
      const { requestId } = await courier.send.message({
        message: {
          to: {
            user_id: "user_123",
          },
          template: "nt_01kx4h2jdafq8bk9aftxak4b40",
        },
      });
      ```

      ```python Python highlight={4} theme={null}
      response = client.send.message(
          message={
              "to": {
                  "user_id": "user_123",
              },
              "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          },
      )
      ```

      ```bash cURL highlight={7} wrap theme={null}
      curl -X POST https://api.courier.com/send \
        -H "Authorization: Bearer $COURIER_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "message": {
            "to": {
              "user_id": "user_123"
            },
            "template": "nt_01kx4h2jdafq8bk9aftxak4b40"
          }
        }'
      ```

      ```ruby Ruby highlight={4} theme={null}
      response = courier.send_.message(
        message: {
          to: {
            user_id: "user_123"
          },
          template: "nt_01kx4h2jdafq8bk9aftxak4b40"
        }
      )
      ```

      ```go Go highlight={5} theme={null}
      response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
      	Message: courier.SendMessageParamsMessage{
      		To: courier.SendMessageParamsMessageToUnion{
      			OfUserRecipient: &shared.UserRecipientParam{
      				UserID: courier.String("user_123"),
      			},
      		},
      		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
      	},
      })
      ```

      ```java Java highlight={3} theme={null}
      SendMessageParams params = SendMessageParams.builder()
          .message(SendMessageParams.Message.builder()
              .to(UserRecipient.builder().userId("user_123").build())
              .template("nt_01kx4h2jdafq8bk9aftxak4b40")
              .build())
          .build();
      SendMessageResponse response = client.send().message(params);
      ```

      ```php PHP highlight={4} theme={null}
      $response = $client->send->message(
        message: [
          'to' => [
            'user_id' => 'user_123',
          ],
          'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
        ],
      );
      ```

      ```csharp C# highlight={5} theme={null}
      SendMessageParams parameters = new()
      {
          Message = new()
          {
              To = new UserRecipient { UserID = "user_123" },
              Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          },
      };

      var response = await client.Send.Message(parameters);
      ```

      ```bash CLI highlight={3} wrap theme={null}
      courier send message \
        --api-key "$COURIER_API_KEY" \
        --message.to '{"user_id": "user_123"}' \
        --message.template nt_01kx4h2jdafq8bk9aftxak4b40
      ```

      ```text MCP theme={null}
      With Courier MCP, send my template to user_123 by email.
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Send to a phone number">
    Pass it inline instead and nothing is stored. Swap this `to` object into the call on the other tab.

    <CodeGroup>
      ```javascript Node.js highlight={4} theme={null}
      const { requestId } = await courier.send.message({
        message: {
          to: {
            phone_number: "+15551234567",
          },
          template: "nt_01kx4h2jdafq8bk9aftxak4b40",
        },
      });
      ```

      ```python Python highlight={4} theme={null}
      response = client.send.message(
          message={
              "to": {
                  "phone_number": "+15551234567",
              },
              "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          },
      )
      ```

      ```bash cURL highlight={7} wrap theme={null}
      curl -X POST https://api.courier.com/send \
        -H "Authorization: Bearer $COURIER_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "message": {
            "to": {
              "phone_number": "+15551234567"
            },
            "template": "nt_01kx4h2jdafq8bk9aftxak4b40"
          }
        }'
      ```

      ```ruby Ruby highlight={4} theme={null}
      response = courier.send_.message(
        message: {
          to: {
            phone_number: "+15551234567"
          },
          template: "nt_01kx4h2jdafq8bk9aftxak4b40"
        }
      )
      ```

      ```go Go highlight={5} theme={null}
      response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
      	Message: courier.SendMessageParamsMessage{
      		To: courier.SendMessageParamsMessageToUnion{
      			OfUserRecipient: &shared.UserRecipientParam{
      				PhoneNumber: courier.String("+15551234567"),
      			},
      		},
      		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
      	},
      })
      ```

      ```java Java highlight={3} theme={null}
      SendMessageParams params = SendMessageParams.builder()
          .message(SendMessageParams.Message.builder()
              .to(UserRecipient.builder().phoneNumber("+15551234567").build())
              .template("nt_01kx4h2jdafq8bk9aftxak4b40")
              .build())
          .build();
      SendMessageResponse response = client.send().message(params);
      ```

      ```php PHP highlight={4} theme={null}
      $response = $client->send->message(
        message: [
          'to' => [
            'phone_number' => '+15551234567',
          ],
          'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
        ],
      );
      ```

      ```csharp C# highlight={5} theme={null}
      SendMessageParams parameters = new()
      {
          Message = new()
          {
              To = new UserRecipient { PhoneNumber = "+15551234567" },
              Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          },
      };

      var response = await client.Send.Message(parameters);
      ```

      ```bash CLI highlight={3} wrap theme={null}
      courier send message \
        --api-key "$COURIER_API_KEY" \
        --message.to '{"phone_number": "+15551234567"}' \
        --message.template nt_01kx4h2jdafq8bk9aftxak4b40
      ```

      ```text MCP theme={null}
      With Courier MCP, send my template to +15551234567 by SMS.
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Notification categories

WhatsApp allows these [notification categories](https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates#whatsapp-notification-categories):

* Marketing
* Authentication
* Utility

Other categories are likely to be rejected, including:

* Account Update
* Alert Update
* Appointment Update
* Auto-Reply
* Issue Resolution
* Payment Update
* Personal Finance Update
* Reservation Update
* Shipping Update
* Ticket Update
* Transportation Update

## WhatsApp template verification

WhatsApp reviews every template against its guidelines before you can send it.

### Create the template

**Structure:** WhatsApp [message templates](https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates) are predefined messages with placeholders for dynamic content. A template can be text, media (images, documents), or interactive (buttons, list messages).

**Categories:** Each template is [categorized](#notification-categories) by use case, such as transactional updates, customer service, or alerts.

### Submit the template for approval

**Open the console:** In the Twilio Console, go to the Messaging section.

**Create the template:** In the WhatsApp Templates section, create a template. Provide the template name, category, language, and message content. Leave out promotional material, which WhatsApp disallows in templates.

**Submit for review:** [Submit](https://www.twilio.com/docs/whatsapp/tutorial/message-template-approvals-statuses) the template for WhatsApp's review.

### WhatsApp approval process

WhatsApp checks the template against its policies. Review takes a few minutes to 24 hours.

Two outcomes:

* **Approved:** The template meets WhatsApp's guidelines. You can now send it through the Twilio API.

* **Rejected:** The template is [rejected](https://www.twilio.com/docs/whatsapp/tutorial/message-template-approvals-statuses#common-rejection-reasons) for promotional content, inappropriate language, or other policy violations. Fix the template and resubmit it.

## Approved templates with Courier

Copy the approved template's [Twilio Content SID](https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates#creating-message-templates-and-submitting-them-for-approval), which starts with `HX`. Paste it into the WhatsApp channel settings of your Courier template. Sends then reference that approved template through the <Endpoint method="POST" path="/send" name="Send a message" href="/docs/api-reference/send/send-a-message">Send API</Endpoint>.

<Frame caption="WhatsApp Template">
  <img src="https://mintcdn.com/courier-4f1f25dc/_N31KC_ZrU1lo5hN/assets/whatsapp.webp?fit=max&auto=format&n=_N31KC_ZrU1lo5hN&q=85&s=23660c5a80b264bb091a6b24b43071b3" alt="A Courier template's WhatsApp channel settings with the Twilio Content SID pasted in" width="1268" height="649" data-path="assets/whatsapp.webp" />
</Frame>

On send, Courier calls Twilio with the template details. Twilio delivers the message over WhatsApp.

<Warning>
  **WhatsApp delivers your Twilio-approved template, not your Courier content.**<br />
  Courier sends the Content SID and its variables, and Twilio renders the approved template. Your Courier template still drives routing, variables, and every other channel.
</Warning>

### Key considerations

**Content:** Keep template content clear and non-promotional. Include every placeholder and give sample values so reviewers have context.

**Localization:** Create and get approval for each language version of the template.

**Monitoring:** Watch template [performance](https://help.twilio.com/articles/360039737753-Recommendations-and-best-practices-for-creating-WhatsApp-Message-Templates). Frequent spam reports can cost you the ability to send. Update templates as WhatsApp guidelines change.

## Overrides

<Doc href="/docs/send/overrides#how-overrides-work">How overrides work</Doc> covers the two levels and which one wins.

A provider override changes the request body Courier sends to Twilio, or swaps the Twilio credentials and the From number.

### Body overrides

A **Content SID is required** on every WhatsApp send. Set it on the template's WhatsApp channel settings, or pass it per send as `override.body.ContentSid`. Without one the send fails with `No Content SID specified.` before reaching Twilio.

Override body keys are capitalized before they are sent, so `contentSid` and `ContentSid` are equivalent. Use an override to select an approved template at send time:

<CodeGroup>
  ```javascript Node.js highlight={11} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        phone_number: "+15555555555",
      },
      providers: {
        "twilio-whatsapp": {
          override: {
            body: {
              ContentSid: "HXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={11} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {
              "phone_number": "+15555555555",
          },
          "providers": {
              "twilio-whatsapp": {
                  "override": {
                      "body": {
                          "ContentSid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXX",
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={14} wrap theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "message": {
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {
          "phone_number": "+15555555555"
        },
        "providers": {
          "twilio-whatsapp": {
            "override": {
              "body": {
                "ContentSid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXX"
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={11} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        phone_number: "+15555555555"
      },
      providers: {
        "twilio-whatsapp": {
          override: {
            body: {
              ContentSid: "HXXXXXXXXXXXXXXXXXXXXXXXXXXX"
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={13} theme={null}
  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  				PhoneNumber: courier.String("+15555555555"),
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"twilio-whatsapp": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"body": map[string]any{
  						"ContentSid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={8} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().phoneNumber("+15555555555").build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("twilio-whatsapp", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "body", java.util.Map.of(
                          "ContentSid", "HXXXXXXXXXXXXXXXXXXXXXXXXXXX"
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={11} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [
        'phone_number' => '+15555555555',
      ],
      'providers' => [
        'twilio-whatsapp' => [
          'override' => [
            'body' => [
              'ContentSid' => 'HXXXXXXXXXXXXXXXXXXXXXXXXXXX',
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={17} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { PhoneNumber = "+15555555555" },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "twilio-whatsapp",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "body": {
                              "ContentSid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXX"
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"phone_number": "+15555555555"}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"twilio-whatsapp": {"override": {"body": {"ContentSid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXX"}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template to +15555555555 on WhatsApp with a Content SID override.
  ```
</CodeGroup>

### Config overrides

Swap Twilio credentials or the "From" number at send time:

<CodeGroup>
  ```javascript Node.js highlight={8-16} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        phone_number: "+15555555555",
      },
      providers: {
        "twilio-whatsapp": {
          override: {
            config: {
              accountSid: "RUNTIME_ACCOUNT_SID",
              authToken: "RUNTIME_AUTH_TOKEN",
              from: "+14155551234",
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={8-16} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {
              "phone_number": "+15555555555",
          },
          "providers": {
              "twilio-whatsapp": {
                  "override": {
                      "config": {
                          "accountSid": "RUNTIME_ACCOUNT_SID",
                          "authToken": "RUNTIME_AUTH_TOKEN",
                          "from": "+14155551234",
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={11-19} wrap theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "message": {
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {
          "phone_number": "+15555555555"
        },
        "providers": {
          "twilio-whatsapp": {
            "override": {
              "config": {
                "accountSid": "RUNTIME_ACCOUNT_SID",
                "authToken": "RUNTIME_AUTH_TOKEN",
                "from": "+14155551234"
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={8-16} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        phone_number: "+15555555555"
      },
      providers: {
        "twilio-whatsapp": {
          override: {
            config: {
              accountSid: "RUNTIME_ACCOUNT_SID",
              authToken: "RUNTIME_AUTH_TOKEN",
              from: "+14155551234"
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={10-18} theme={null}
  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  				PhoneNumber: courier.String("+15555555555"),
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"twilio-whatsapp": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"config": map[string]any{
  						"accountSid": "RUNTIME_ACCOUNT_SID",
  						"authToken": "RUNTIME_AUTH_TOKEN",
  						"from": "+14155551234",
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={6-12} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().phoneNumber("+15555555555").build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("twilio-whatsapp", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "config", java.util.Map.of(
                          "accountSid", "RUNTIME_ACCOUNT_SID",
                          "authToken", "RUNTIME_AUTH_TOKEN",
                          "from", "+14155551234"
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={8-16} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [
        'phone_number' => '+15555555555',
      ],
      'providers' => [
        'twilio-whatsapp' => [
          'override' => [
            'config' => [
              'accountSid' => 'RUNTIME_ACCOUNT_SID',
              'authToken' => 'RUNTIME_AUTH_TOKEN',
              'from' => '+14155551234',
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={9-25} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { PhoneNumber = "+15555555555" },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "twilio-whatsapp",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "config": {
                              "accountSid": "RUNTIME_ACCOUNT_SID",
                              "authToken": "RUNTIME_AUTH_TOKEN",
                              "from": "+14155551234"
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"phone_number": "+15555555555"}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"twilio-whatsapp": {"override": {"config": {"accountSid": "RUNTIME_ACCOUNT_SID", "authToken": "RUNTIME_AUTH_TOKEN", "from": "+14155551234"}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template to +15555555555 on WhatsApp with different Twilio credentials.
  ```
</CodeGroup>

## Provider details

```text theme={null}
twilio-whatsapp
```

Courier recommends routing to the channel. Naming this key in `routing.channels` instead is supported, and sends through just this provider.

<Card title="Send to a specific provider" icon="bullseye-arrow" href="/docs/send/send-to-a-provider" horizontal arrow="true">
  When that is worth doing, and what you give up: failover, channel priority, and providers you add later.
</Card>
