# iMessage

Let people text your agent. The `linq` connector answers them over iMessage on your own Linq line.

## Answer on iMessage

Use your Linq connection:

```yaml title="agents/support/agent.yaml"
name: support
mode: text
llm: llm-fast
connectors:
  - name: linq
    connection: acme-imessage # the label of your Linq connection
```

You need a Linq API token, and your line's number in E.164. Setup takes three steps:

1. **Subscribe at Linq.** Pick a name for your Linq account, such as `acme-linq`. At Linq, create a webhook subscription for the `message.received` event to `$STREAM_ACCELERATION_URL/v1/connectors/events/linq/acme-linq?version=2026-02-03`. `$STREAM_ACCELERATION_URL` is your router's URL. Keep the subscription's signing secret. It starts with `whsec_`.
2. **Save your Linq account.** On the Stream Dashboard, open **Library > Connectors**, then **Linq**. Choose **Set OAuth client**. Fill **Provider app ID** with `acme-linq` and **Signing secret** with the secret from step 1. Leave the other fields empty, then choose **Save client**.
3. **Create the connection.** On the same page, choose **Create connection**. Choose **App** as the **Owner**. Enter `acme-imessage` as the **Label**, your line's number as `phone_number`, such as `+12025550100`, and Linq's API token as the **Token**. Choose **Create connection**.

Sync the agent:

```sh
curl -fsSL https://getstream.io/cli/beta/install.sh | bash # the agents commands are in the beta CLI
getstream agents sync support
```

From an iPhone, text "What is your return policy?" to your Linq line. The reply comes back in the same chat.

## Conversations

- Each chat is one conversation. Text "My name is Ana", then "What is my name?", and the agent answers "Your name is Ana."
- Stream Chat keeps the conversation in one channel per chat, with the person's messages and the agent's replies.
- A photo reaches the agent. Send a photo with "What is in this photo?", and the agent answers about the photo.
- If photos do not reach the agent, save the Linq token again. On the connection's page, choose **Replace token** and enter the Linq API token again.

## Set it up from your backend

Step 1 is one call to Linq's API, with your Linq API token:

```bash
curl -X POST "https://api.linqapp.com/api/partner/v3/webhook-subscriptions" \
  -H "Authorization: Bearer $LINQ_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_url": "$STREAM_ACCELERATION_URL/v1/connectors/events/linq/acme-linq?version=2026-02-03", "subscribed_events": ["message.received"]}'
```

Put your router URL in place of `$STREAM_ACCELERATION_URL`. Linq returns the subscription's `signing_secret`.

Steps 2 and 3 are three calls to Stream. `$SERVER_TOKEN` is a [server token](https://getstream.io/agents/docs/go-golang/auth/):

```bash
curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connectors/linq/oauth-client" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"provider_app_id": "acme-linq", "signing_secret": "whsec_..."}'

curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connections" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connector_id": "linq", "owner": {"type": "app"}, "label": "acme-imessage", "inputs": {"phone_number": "+12025550100"}}'

curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connections/$CONNECTION_ID/credentials" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expected_revision": 1, "values": {"token": "<Linq API token>"}}'
```

`$CONNECTION_ID` is the `id` the second call returns. After the third call, the connection is `connected`.

## Keywords

Stream handles these, not the agent:

- HELP: Stream answers with its help text, "Reply STOP to unsubscribe."
- STOP: the person is opted out. They get no confirmation, and nothing more is sent to them until they send START.
- START: the person is opted back in. Stream answers "You are subscribed again. Reply STOP to unsubscribe.", and the agent answers their next message.

## Going further

- [Connectors](https://getstream.io/agents/docs/go-golang/connectors/): Whose account, the catalog, and the keys of a connector entry.
- [SMS](https://getstream.io/agents/docs/go-golang/connectors/sms/): Answer over SMS on your own Telnyx number.
- [Slack](https://getstream.io/agents/docs/go-golang/connectors/slack/): Answer in Slack threads as your workspace's bot.
- [Creating an agent](https://getstream.io/agents/docs/go-golang/creating-an-agent/): The agent folder, and every key of agent.yaml.

---

For the most recent version of this documentation, visit [https://getstream.io/agents/docs/go-golang/connectors/imessage/](https://getstream.io/agents/docs/go-golang/connectors/imessage/).