Relay docs
API Reference

Overview

Programmatic access to Relay conversations, contacts, companies, and products.

The Relay API is a REST API for reading and writing conversations, contacts, companies, and products in your workspace. It runs alongside the realtime product, so a message you push through the API appears live in the dashboard for your agents.

Prefer the terminal? The Relay CLI wraps this API for scripting and one-off tasks, and can migrate your data from Crisp in one command.

Authentication

Every request is authenticated with a workspace API key sent as a Bearer token:

curl https://api.superrelay.ai/v1/public/conversations \
  -H "Authorization: Bearer rl_live_xxxxxxxxxxxxxxxxxxxxxxxx"

Create and manage keys in Settings → API Keys. Keys are scoped to a single workspace and to a set of permissions:

ScopeGrants
conversations:readList and read conversations and their messages
conversations:writeCreate conversations, push messages, update parameters
contacts:readList and read contacts
contacts:writeCreate and update contacts
companies:readList and read companies (and the deprecated /stores alias); a company's contacts also need contacts:read
companies:writeCreate and update companies (and the deprecated /stores alias)
products:readList and read products

The plaintext key is shown once at creation — store it securely. If a key is lost or leaked, revoke it and create a new one.

products:read and companies:read / companies:write were added with their resources. Keys created before them don't carry them — create a new key (all scopes are on by default) or edit the existing key's scopes. Two exceptions: reading a conversation's product and filtering by productId only need conversations:read, and keys holding contacts:read / contacts:write keep working for /companies (and /stores) until the stores sunset.

Products

Every conversation belongs to at most one product — the thing you support: a SaaS product, a website, an app. Products decide which knowledge base and AI context apply, and they are how you filter and report. See Products and routing for how conversations get their product.

In the API:

  • Conversations carry a product object ({ id, name }), or null when the conversation has not been routed or triaged yet.
  • GET /v1/public/conversations?productId=<id> lists one product's conversations; ?productId=none lists the ones that still need a product.
  • POST /v1/public/conversations takes an optional productId. Omit it to inherit the inbox's product; pass null to leave the conversation unassigned on purpose.
  • GET /v1/public/products and GET /v1/public/products/{id} list and read products. They are read-only — create, edit, and archive products in Settings → Products.

Companies

A company is the organization a contact belongs to — a customer account, a company, or a store for e-commerce products. Contacts carry a company object ({ id, name }) and a companyId; PATCH /v1/public/contacts/{id} takes companyId to link or unlink (null). GET /v1/public/companies/{id}/contacts lists a company's people.

Companies are also created for you: when a customer's signed identity carries an organization claim, Relay resolves it to a company by externalId (creating one on first sight) and links the contact. Set externalId to your own account id so both paths meet.

Pagination

List endpoints are cursor-paginated and return a consistent envelope:

{
  "data": [],
  "has_more": true,
  "next_cursor": "eyJ2IjoxLCJ0cyI6..."
}

Pass next_cursor back as the cursor query parameter (and limit, 1–200) to fetch the next page. Cursors are opaque — treat them as a token, don't parse them.

Errors

Errors return the appropriate HTTP status with a JSON body of the form { "error": "message" }. Common cases: 401 (missing/invalid/expired key), 403 (key missing the required scope), 404 (resource not in this workspace), 400 (validation error — for example a productId that is neither a UUID nor none).

Stores deprecation

stores is the old name of the companies resource. It is now a pure alias: /v1/public/stores* calls the same handlers as /v1/public/companies*, returns the same fields and the same ids, and accepts the same scopes. Switching is a rename.

  • Every /v1/public/stores* route keeps working until 16 February 2027.
  • Responses carry an RFC 9745 Deprecation header (a Structured Field Date such as @1786752000 — the moment the resource became deprecated), an RFC 8594 Sunset: Tue, 16 Feb 2027 00:00:00 GMT header, and a Link: <…>; rel="deprecation" header pointing here.
  • On contacts, storeId stays as a deprecated alias of companyId for the same window.
  • After the sunset date /stores* and storeId are removed.

Migration: replace /stores with /companies in paths, storeId with companyId on contacts, and give new API keys the companies:read / companies:write scopes (existing contacts:* keys keep working until the sunset).

On this page