Skip to content
Docs

Connect a chat app or tool

POST
/api/workspaces/{ws}/connections

type and values follow GET /api/catalog: e.g. { "kind": "tool", "type": "github", "name": "GitHub", "values": { "token": "github_pat_…" } }. A tool whose catalog entry has connect.checks is checked with the tool first: the connection comes back with account (who the key belongs to). A key the tool refuses is never saved: 400 { error, reason: "credential" | "permission" }, the error saying what to fix. When the tool couldn't be reached, reason is "unreachable"; send the same request with skipCheck: true to save it anyway. Where the catalog entry says registersWebhook, Roster registers its own webhook at the tool; webhookProblem says so if it couldn't.

Authorization

session
cookiebetter-auth.session_token<token>

Set by POST /api/auth/sign-in/email.

Path Parameters

ws*string

The workspace id (from GET /api/me).

Request Body

application/json
  1. body
kind*string
Value in"chat""tool"
type*string
Length1 <= length
name*string
Length1 <= length <= 80
values?
Default{}
skipCheck?boolean

Response Body

The connection.

application/json
Example Request
curl -X POST 'https://app.useroster.work/api/workspaces/string/connections' \  -H 'Content-Type: application/json' \  -d '{  "kind": "chat",  "type": "string",  "name": "string"}'
Example Response
{  "id": "8d1e5b2c-0f3a-4e7b-9c6d-1a2b3c4d5e6f",  "kind": "tool",  "type": "github",  "name": "GitHub",  "settings": {},  "secretsSet": [    "token"  ],  "status": "connected",  "statusDetail": null,  "account": "acme-studio",  "checkedAt": "2026-11-03T09:00:00.000Z",  "createdAt": "2026-11-03T09:00:00.000Z"}