> ## 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.

# LINE

> Send and receive LINE messages via the LINE Messaging API and the Orbit Messaging API

# LINE

Orbit's LINE channel wraps the [LINE Messaging API](https://developers.line.biz/en/docs/messaging-api/) so you can send and receive messages from the same unified Messaging surface used for every other channel. Each Orbit organization connects one or more LINE Messaging API channels; inbound webhook delivery and signature verification are handled automatically.

LINE is fully multi-tenant: Orbit resolves the receiving tenant from the LINE channel ID (`destination`) on every inbound event, so multiple organizations can run their own LINE bots through the same platform.

## Send a message

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/line \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "U4af4980629...",
    "body": "Welcome! Reply with a number to continue.",
    "type": "text"
  }'
```

### Request body

| Field      | Type   | Required | Description                                                                                                                                                          |
| ---------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `to`       | string | yes      | Recipient LINE id — a user id (`U…`), group id (`C…`), or room id (`R…`) obtained from an inbound event.                                                             |
| `body`     | string | yes      | Message body, 1–5000 characters.                                                                                                                                     |
| `type`     | string | no       | LINE message type. One of `text`, `image`, `video`, `audio`, `location`, `sticker`, `flex`. Defaults to `text`.                                                      |
| `metadata` | object | no       | Optional flat map of string→string values carrying the secondary per-message options the non-text types read (see below). Echoed back on delivery + status webhooks. |

The message text goes in the top-level `body` field and the send `type` in the top-level `type` field. The secondary per-message options the non-text types read (`preview_url`, `duration`, `location_title`, `location_address`, `latitude`, `longitude`, `package_id`, `sticker_id`, `flex_contents`) are passed under `metadata`, whose values are all strings. A `type` set under `metadata` is ignored — only the top-level `type` selects the LINE message type.

The sender is selected automatically from the LINE channel credentials connected to your organization — you do not pass a bot token or channel id on the request.

### Response

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

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

## Capabilities

* **Message types** — `text`, `image`, `video`, `audio`, `location`, `sticker`, and `flex` (fully custom Flex Message layouts, which also cover button / confirm / carousel layouts).
* **User, group, and room targeting** — push to a user (`U…`), group (`C…`), or room (`R…`) id surfaced by an inbound event.
* **Inbound webhooks** — user messages, follows, joins, and postbacks are POSTed to your registered webhook endpoint with the standard Orbit inbound envelope (`channel: "line"`).
* **Media re-hosting** — inbound image / video / audio / file content is downloaded from `api-data.line.me` and re-hosted on Orbit storage, so attachment URLs stay reachable after LINE's short-lived content URL expires.
* **Signature verification** — every inbound request is verified against the connected channel's `channel_secret` (HMAC-SHA256, `x-line-signature` header) before it reaches your webhook.

## Rate limits

Outbound `POST /messages/line` is capped at **80 requests/minute per tenant**. 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).

## Onboarding flow

1. In the [LINE Developers Console](https://developers.line.biz/console/), create (or open) a **Messaging API channel** for your LINE Official Account.
2. From the channel's **Messaging API** tab, copy the **Channel access token (long-lived)** and from the **Basic settings** tab copy the **Channel secret**.
3. In the Orbit dashboard, navigate to **Channels → LINE → Connect** and paste both values. Orbit stores them encrypted at rest (`enc:v1:` envelope) under your organization's `settings.channels.line` and never echoes them back through any API response.
4. Set the channel's **Webhook URL** in the LINE Developers Console to `https://api.orbit.devotel.io/api/v1/webhooks/inbound/line` and enable **Use webhook**. Orbit identifies the receiving tenant from the LINE channel id (`destination`) on each event, so all tenants share this single URL.

### Credential handling — your responsibility

The channel access token and channel secret are bearer credentials. Anyone holding them can send messages as your LINE Official Account and read inbound events. Orbit encrypts both at rest and masks them in the dashboard after submit, but their safety upstream of Orbit (your password manager, CI/CD variables, screenshots) is yours to protect:

* **Never commit a channel access token or channel secret to git**, public or private.
* **Rotate immediately** from the LINE Developers Console if you suspect exposure, then re-paste the new values in Orbit — conversation history is keyed by channel id, not by the token, so it is preserved across rotation.
* **Scope each environment to its own LINE channel** (dev / staging / production) so a leaked dev credential cannot reach customer conversations.

## Inbound webhook routing

LINE delivers user messages and events to `POST /api/v1/webhooks/inbound/line`. Orbit:

1. Reads the `destination` (LINE channel id) from the untrusted payload and resolves the owning tenant.
2. Verifies the `x-line-signature` HMAC-SHA256 header against that tenant's stored `channel_secret`.
3. Normalizes each LINE event into the standard inbound envelope and forwards it to the webhook endpoint configured under **Settings → Webhooks**, signed with the Standard-Webhooks scheme used across Orbit.

Delivery-status callbacks (LINE `delivery` events) land separately on `POST /api/v1/webhooks/dlr/line` and are used to advance the outbound message lifecycle to `delivered` / `failed`; you do not need to register for these — Orbit configures them as part of connect.

## Common errors

| Code                  | HTTP | Cause                                                                                                            | Fix                                                                                 |
| --------------------- | ---- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `VALIDATION_ERROR`    | 422  | `to` or `body` missing, `body` exceeds 5000 characters, or a `flex` message's `flex_contents` is not valid JSON. | Correct the request body and retry.                                                 |
| `INVALID_RECIPIENT`   | 422  | `to` is empty or not a usable LINE recipient id.                                                                 | Send to a user (`U…`), group (`C…`), or room (`R…`) id taken from an inbound event. |
| `MESSAGE_SEND_FAILED` | 502  | LINE's Messaging API rejected the push or was unreachable.                                                       | Check the failure reason on the message's status webhook, then retry.               |
| `RATE_LIMITED`        | 429  | More than 80 sends/minute for the tenant.                                                                        | Honour the `Retry-After` header; stage bulk sends through the campaigns API.        |

`LINE_INVALID_TOKEN` (401) is returned only when **connecting** credentials under **Channels → LINE**, if the channel access token is expired or invalid at connect time. It is not raised on the send path; a token rotated after connect surfaces as `MESSAGE_SEND_FAILED` until you re-paste the current token.

## Pricing

The LINE Messaging API has its own message quota and pricing set by LINE for your Official Account. Orbit charges a flat per-1M platform fee for delivery and inbound webhook fan-in. See the [pricing page](https://orbit.devotel.io/pricing).
