---
title: Vercel Chat SDK | API Docs
description: Build agents on iMessage and SMS with Vercel's Chat SDK, powered by Linq.
---

[Chat SDK](https://chat-sdk.dev) is Vercel’s framework for building chat agents. Write your bot’s logic once and run it across platforms through adapters. The Linq adapter is the iMessage and SMS channel — your agent sends and receives texts, media, and tapback reactions over Apple Messages and SMS, using the same handlers you’d write for any other platform.

The adapter is built and maintained by Linq and lives at [github.com/linq-team/linq-chat-sdk](https://github.com/linq-team/linq-chat-sdk).

## Install

Terminal window

```
npm install @linqapp/chat-sdk-adapter chat
```

`chat` is Vercel’s Chat SDK core; `@linqapp/chat-sdk-adapter` is the Linq channel.

## Quickstart

```
import { createLinqAdapter } from "@linqapp/chat-sdk-adapter";
import { Chat } from "chat";


const chat = new Chat({
  userName: "mybot",
  adapters: {
    linq: createLinqAdapter({
      apiKey: process.env.LINQ_API_KEY!,
      signingSecret: process.env.LINQ_WEBHOOK_SECRET!,
    }),
  },
});


chat.onDirectMessage(async (thread, message) => {
  await thread.subscribe();
  await thread.post(`you said: ${message.text}`);
});


chat.onReaction(["thumbs_up"], async (event) => {
  await event.thread.post("appreciate the tapback 🫡");
});
```

Then route Linq webhooks to the adapter from any fetch-style handler:

```
// e.g. a Next.js / Nitro / Hono POST route
export default async (request: Request) => chat.webhooks.linq(request);
```

## Configuration

| Option          | Required | Description                                                                                                                                                                                    |
| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`        | yes      | Your Linq [API key](/getting-started/authentication/index.md).                                                                                                                                 |
| `signingSecret` | yes      | The signing secret from your [webhook subscription](/guides/webhooks/subscriptions/index.md). Inbound requests are verified with HMAC-SHA256 over `{timestamp}.{body}` with replay protection. |
| `baseURL`       | no       | Override the API base URL.                                                                                                                                                                     |

## Receiving messages

The adapter is webhook-driven. [Create a webhook subscription](/guides/webhooks/subscriptions/index.md) pointing at your route and subscribe to at least:

- `message.received`
- `reaction.added`
- `reaction.removed`

See [webhook events](/guides/webhooks/events/index.md) for the full payload reference. Any event type the adapter doesn’t handle is acknowledged with a `200` and ignored.

## What’s supported

The adapter maps Linq onto the Chat SDK’s thread/message/reaction model, so standard APIs (`thread.post`, `thread.subscribe`, `onDirectMessage`, `onNewMessage`, `onReaction`) work unchanged.

- **Text** — inbound and outbound, in DMs and [group chats](/guides/chats/group-chats/index.md).
- **Media** — inbound images, audio, and files arrive as attachments; outbound `attachments`/`files` are sent as [media parts](/guides/messaging/attachments/index.md) (public HTTPS URLs by reference, or pre-uploaded for larger/raw files).
- **Reactions** — iMessage tapbacks map to Chat SDK emoji both ways (see below).
- **Typing indicators** — supported in DMs ([Linq rejects typing in groups](/guides/chats/typing-indicators/index.md)).
- **Edits** — outbound message text can be edited.

Streaming is buffered (recipients see one final message). Stickers, message deletion, and modals have no iMessage equivalent and are not supported.

## Reactions

Standard tapbacks map to normalized Chat SDK emoji in both directions:

| Linq tapback | Chat SDK emoji |
| ------------ | -------------- |
| `like`       | `thumbs_up`    |
| `dislike`    | `thumbs_down`  |
| `love`       | `heart`        |
| `laugh`      | `laugh`        |
| `emphasize`  | `exclamation`  |
| `question`   | `question`     |

Custom emoji reactions pass through the default resolver (e.g. `👍` → `thumbs_up`); anything unmapped falls back to the raw emoji. See [reactions](/guides/messaging/reactions/index.md) for how Linq models tapbacks.

## Thread IDs

Thread IDs are stable and always take the form `linq:{chatId}`, so a conversation maps to the same Chat SDK thread whether it first arrives via webhook or API.

## Example app

The repo includes a [full example](https://github.com/linq-team/linq-chat-sdk/tree/main/apps/api) — a server running one AI bot across Linq, Telegram, and WhatsApp from a single set of handlers.
