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

# WeChat

> Send WeChat Official Account template messages through the Orbit Messaging API

# WeChat

WeChat is China's super-app. Orbit's WeChat channel wraps the WeChat Official Account template-message API so you can deliver pre-approved template messages to your followers from the same unified Messaging surface used for every other channel.

<Note>
  WeChat is a **beta** channel. The send and receive paths are wired end to end, but onboarding still requires you to provision a WeChat Official Account and a valid OA access token.
</Note>

## How OA template messages work

WeChat Official Account messaging is **template-only**: you send a pre-approved template message to a follower's `openid`. `template_name` selects the approved template id and `template_params` fills the template's named `{{key.DATA}}` placeholders. An optional `metadata.url` deep-links the message to an H5 page. A send without an approved `template_name` is rejected with `VALIDATION_ERROR` (422).

## Send a WeChat message

Send a single WeChat OA template message with `POST /api/v1/messages/wechat` — the direct per-message endpoint, the same shape as every other channel's send route (`/sms`, `/line`, `/zalo`). Select the approved template with `template_name` and fill its `{{key.DATA}}` placeholders with `template_params`.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/wechat \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "oABCdef1234567890ghijklmno",
    "template_name": "ORDER_SHIPPED_V2",
    "template_params": { "order_id": "A1024", "carrier": "SF Express" },
    "metadata": { "url": "https://h5.example.com/orders/A1024" }
  }'
```

### Request body

| Field             | Type   | Required | Description                                                                            |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------- |
| `to`              | string | yes      | Recipient `openid` (the follower's Official-Account-scoped id).                        |
| `template_name`   | string | yes      | The approved WeChat template id.                                                       |
| `template_params` | object | no       | Flat string→string map filling the template's `{{key.DATA}}` placeholders.             |
| `metadata.url`    | string | no       | Optional H5 deep-link opened when the follower taps the message.                       |
| `metadata`        | object | no       | Flat map of string→string values. Echoed back on delivery and status webhooks.         |
| `scheduled_at`    | string | no       | RFC 3339 timestamp to defer the send; the message is queued as `scheduled` until then. |

The sender is selected automatically from the WeChat Official Account credentials connected to your organization — you do not pass an access token on the request.

### Response

`202 Accepted` — the message is persisted and queued for delivery; the terminal `delivered` / `failed` state arrives later via the delivery-status webhook.

```json theme={null}
{
  "data": {
    "id": "msg_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "status": "queued",
    "channel": "wechat"
  },
  "meta": {
    "request_id": "req_xyz789",
    "timestamp": "2026-06-08T00:00:00Z"
  }
}
```

## Bulk sends

To broadcast the same approved template to many followers at once, submit a [campaign](/api-reference/endpoints/campaigns) with `channel` set to `wechat`. The campaign fans out one templated send per recipient across your audience, reusing the same OA credentials, `template_name`, and `template_params` shape described above — use it instead of looping the single-send endpoint yourself.

## Rate limits

The direct `POST /messages/wechat` endpoint is capped at **80 requests/minute per organization**. Bursts above the cap receive `429` with a `Retry-After` header; back off and retry, or stage high-volume sends through the campaigns API. See [Rate Limits](/guides/rate-limits).

## Configuration

WeChat is a bring-your-own-credential channel. You can connect it per organization in the dashboard, or set a platform-default credential for the whole cluster.

### Per organization (recommended)

1. Register a WeChat Official Account and create your template messages in the WeChat OA admin console. Each approved template receives a template id.
2. Obtain the OA **access token** via the `cgi-bin/token` (or stable-token) grant. The token is short-lived (\~2 hours); rotate it centrally before it expires.
3. In the Orbit dashboard, go to **Settings → Channels → WeChat** and paste the access token. Orbit stores it encrypted at rest (`enc:v1:` envelope) under your organization's `settings.channels.wechat` and never echoes it back through any API response.

Per-organization credentials take precedence; when an organization has none, sends fall through to the platform default below.

### Platform default

An operator can register a single cluster-wide WeChat provider by setting one environment variable. When it is unset the channel stays unregistered and a send fails closed with `CHANNEL_NOT_CONFIGURED`.

| Variable                      | Description                           |
| ----------------------------- | ------------------------------------- |
| `DEVOTEL_WECHAT_ACCESS_TOKEN` | WeChat Official Account access token. |

### Credential handling — your responsibility

The OA access token is a bearer credential. Anyone holding it can send messages as your Official Account. Orbit encrypts it at rest and masks it in the dashboard after submit, but its safety upstream of Orbit (your password manager, CI/CD variables, screenshots) is yours to protect:

* **Never commit an access token to git**, public or private.
* **Rotate immediately** through the WeChat grant if you suspect exposure, then re-paste the new value in Orbit.
* **Scope each environment to its own Official Account** so a leaked dev token cannot reach customer conversations.

## Inbound and delivery status

Inbound replies and delivery receipts are normalized by the Orbit messaging gateway and relayed to your account automatically — there is no WeChat webhook for you to register. Replies arrive on the standard `message.received` webhook with `channel: "wechat"`; WeChat's `TEMPLATESENDJOBFINISH` callback advances your outbound message to `delivered` / `failed`. Subscribe to these under **Settings → Webhooks**.

## Common errors

| Code                     | HTTP | Cause                                                                                      | Fix                                                                                           |
| ------------------------ | ---- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| `INVALID_RECIPIENT`      | 422  | `to` (the recipient `openid`) is missing or empty.                                         | Supply the follower's `openid`.                                                               |
| `VALIDATION_ERROR`       | 422  | The send has no approved `template_name` — OA messaging is template-only.                  | Provide an approved WeChat template id.                                                       |
| `CHANNEL_NOT_CONFIGURED` | 503  | No WeChat credentials are connected for the organization and no platform default is set.   | Connect an access token under **Settings → Channels → WeChat**.                               |
| `MESSAGE_SEND_FAILED`    | 502  | WeChat returned a non-zero `errcode` (expired token, unapproved template, not a follower). | Inspect the WeChat `errcode` in the error message; refresh the token or correct the template. |
| `RATE_LIMITED`           | 429  | More than 80 sends/minute for your organization on `POST /messages/wechat`.                | Honour the `Retry-After` header; stage bulk sends through the campaigns API.                  |

## Pricing

WeChat Official Account messaging is governed by WeChat's own template and quota rules. Orbit charges a flat per-1M platform fee for delivery and inbound webhook fan-in. See the [pricing page](https://orbit.devotel.io/pricing).
