# Chat apps

> Build apps that post rich, interactive messages, modals and a Home tab in Repzo Chat — with the same Block Kit JSON and API names as Slack.

A chat app (a **bot**) is a member of Repzo Chat that your code drives. It posts messages built from [Block Kit](https://workstation.repzo.com/docs/developers/block-kit) blocks, hears when people click its buttons or fill in its forms, opens [modals](https://workstation.repzo.com/docs/developers/chat-apps/modals), and can give each person a [Home tab](https://workstation.repzo.com/docs/developers/chat-apps/app-home).

If you have built a Slack app, you already know most of it: the payloads, method names (`chat.postMessage`, `views.open`, …) and interaction shapes are Slack's. The differences are listed on each reference page under **How Repzo Chat differs from Slack**.

> **Building with an AI assistant?**
>
> Every docs page has a **Copy page** button, and each page is also plain Markdown at its URL plus `.md`. Point your assistant at [/docs/llms.txt](https://workstation.repzo.com/docs/llms.txt) for the index, or [/docs/llms-full.txt](https://workstation.repzo.com/docs/llms-full.txt) for everything in one file.

## Create a bot

1. Open **Settings → Integrations & Developers → Developer Apps** and choose the **Bots** tab.
2. Create a bot. Give it a name and avatar — that's how it appears in Chat.
3. Copy its `foxa-*` token when it is shown. Workstation stores only a hash and can't show it again.
4. Under **Interactivity**, set the HTTPS URL that should receive clicks and form submissions. Copy the **signing secret** shown once — you need it to [verify requests](#verify-requests-from-repzo).
5. Add the bot to the channels it should post in (public channels work without joining when the bot has `chat:write.public`).

Keep the token in a secret store or environment variable. Never commit it.

## Two ways to call Workstation

| | Slack-compatible bot API | Public REST API v1 |
|---|---|---|
| Base path | `/api/bot/<method>` | `/api/v1/...` |
| Style | Slack method names and bodies, answers `{ "ok": true, ... }` | REST resources, OpenAPI-documented at [/api/v1/docs](https://workstation.repzo.com/api/v1/docs) |
| Best for | Porting Slack apps, Slack SDKs pointed at Repzo | New integrations that also use other Workstation resources |

Both take a `Authorization: Bearer foxa-…` header and the same Block Kit JSON.

### Bot API methods

| Method | What it does |
|---|---|
| `POST /api/bot/chat.postMessage` | [Post a message](https://workstation.repzo.com/docs/developers/chat-apps/sending-messages) (`channel`, `text`, `blocks`, `attachments`, `thread_ts`) |
| `POST /api/bot/chat.update` | Edit a message your bot posted (`ts`, `text`, `blocks`, `attachments`) |
| `POST /api/bot/chat.delete` | Delete a message your bot posted (`ts`) |
| `POST /api/bot/chat.postEphemeral` | [Post a message only one person sees](https://workstation.repzo.com/docs/developers/chat-apps/ephemeral-messages) |
| `POST /api/bot/views.open` / `views.push` / `views.update` | [Open, stack and update modals](https://workstation.repzo.com/docs/developers/chat-apps/modals) |
| `POST /api/bot/views.publish` | [Set a person's Home tab](https://workstation.repzo.com/docs/developers/chat-apps/app-home) |
| `GET /api/bot/channels.list` / `channels.info` | List public channels / look one up |
| `GET /api/bot/files/:id` | Download a file someone attached in your form (the link comes in the payload) |

`channel` accepts a channel id or its short name (`sales` or `#sales`).

### Scopes

A bot's scopes are set when it is created: `chat:write.public` (post in public channels), `chat:write` (post anywhere it's a member), `chat:write.thread`, `chat:update`, `chat:delete` and `channels:read`.

## Quick start

Post a message with a button:

```bash
curl -X POST https://workstation.repzo.com/api/bot/chat.postMessage \
  -H "Authorization: Bearer $REPZO_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "sales",
    "text": "New deal: Acme expansion",
    "blocks": [
      { "type": "section", "text": { "type": "mrkdwn", "text": "*New deal:* Acme expansion — $12,000" } },
      { "type": "actions", "elements": [
        { "type": "button", "action_id": "approve", "style": "primary", "text": { "type": "plain_text", "text": "Approve" }, "value": "deal-42" }
      ] }
    ]
  }'
```

When someone clicks **Approve**, your interactivity URL receives a [`block_actions` payload](https://workstation.repzo.com/docs/developers/chat-apps/interactivity).

## Verify requests from Repzo

Every request Workstation sends your app — clicks, form submissions, option lookups, events — is signed with your signing secret:

```http
X-Fox-Timestamp: 1791799555
X-Fox-Signature: sha256=5f2c…
```

The signature is `HMAC-SHA256(secret, "<timestamp>.<raw request body>")` as hex. Recompute it over the raw body, compare in constant time, and reject requests older than five minutes.

```js

function isFromRepzo(rawBody, headers, secret) {
  const timestamp = headers["x-fox-timestamp"];
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const given = headers["x-fox-signature"] ?? "";
  return given.length === expected.length && crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}
```

> **Differs from Slack**
>
> Slack signs with `X-Slack-Signature: v0=…`. Repzo uses the `X-Fox-*` headers above, and sends interaction payloads as JSON (`Content-Type: application/json`), not as a form-encoded `payload=` field.

## Sandboxes

A [sandbox](https://workstation.repzo.com/docs/administration/settings) has its own Developer Apps. Requests to your own bot endpoints are delivered from sandboxes too, so you can test an app end to end without touching the live workspace.

## Next steps

- [Sending messages](https://workstation.repzo.com/docs/developers/chat-apps/sending-messages)
- [Interactivity](https://workstation.repzo.com/docs/developers/chat-apps/interactivity)
- [Modals](https://workstation.repzo.com/docs/developers/chat-apps/modals)
- [App Home](https://workstation.repzo.com/docs/developers/chat-apps/app-home)
- [Ephemeral messages](https://workstation.repzo.com/docs/developers/chat-apps/ephemeral-messages)
- [Formatting text](https://workstation.repzo.com/docs/developers/chat-apps/formatting-text)
- [Block Kit reference](https://workstation.repzo.com/docs/developers/block-kit)
