REST API
The Chatvia REST API lets your own software do what your team does in the dashboard. Your backend sends a request over HTTPS, and Chatvia answers with JSON.
Use it when a task should happen without a person clicking through the dashboard. Some examples:
- Your shop adds a new product page. A script adds the page to the support agent's knowledge.
- A customer signs up on your site. Your backend creates a chatter account for them and hands them a sign-in link to your agent.
- Your CRM wants to show the agent's answer inside a ticket. It opens a conversation and sends the customer's question.
- Your deploy pipeline runs the agent's evals and stops the release when the pass rate drops.
This section is for developers. Each page below covers one group of endpoints, with the parameters, a curl example and an example response.
| Page | What it covers |
|---|---|
| Agents | List, create, update and delete agents. List saved prompts. |
| Sources | Add and delete files, texts, websites and Q&A pairs. |
| Functions | Manage webhook functions and attach them to agents. |
| Connectors | Manage MCP servers and attach them to agents. |
| Conversations | Chat with an agent, read and delete chat history. |
| Chatters | Manage chatter accounts, their access and sign-in links. |
| Teams and users | Manage teams, roles and who holds them. |
| Forms and leads | Manage inline forms, read and export submissions. |
| Evals | Start eval runs and read their results. |
| Topics | Manage the topics conversations are tagged with. |
| Analytics and audit log | Read usage numbers and the tool-call audit log. |
A first request
This request lists your agents:
curl https://chat.example.com/api/v1/agents \
-H "Authorization: Bearer $CHATVIA_API_KEY"The answer is one page of agents:
{
"data": [
{
"id": "a3f9c2e17b4d08",
"team": { "id": "0199f3a2-1c4e-7b1a-9d2e-5f6a7b8c9d01", "name": "Support" },
"name": "Help Desk",
"is_public": true,
"metadata": {},
"source": "dashboard",
"system_instructions": "You answer questions about our shop.",
"prompt_id": null,
"slug": "help-desk",
"url": "https://chat.example.com/chat/help-desk",
"permanent_url": "https://chat.example.com/chat/a3f9c2e17b4d08",
"created_at": "2026-10-01T08:12:44+00:00",
"updated_at": "2026-10-20T15:03:10+00:00"
}
],
"next_cursor": null
}Base URL
Every endpoint lives under /api/v1 on your Chatvia server:
https://chat.example.com/api/v1Here https://chat.example.com stands for your install's own address (APP_URL). Use the address you open the dashboard on.
Send request bodies as JSON with Content-Type: application/json. The one exception is a file upload, which is multipart/form-data. See Add a file.
Authentication
Every request carries an API key. An API key is a secret string that tells Chatvia who is calling. Send it in the Authorization header as a bearer token:
Authorization: Bearer YOUR_API_KEYTo get a key, open Workspace → Integrations → API Keys and click Generate key. The key is shown once. API keys has the steps and tips for keeping keys safe.
Keep keys on your server. Never put a key in a web page or a mobile app, where anyone can read it.
A key stops working when:
- someone clicks Revoke on it.
- the account that made it is deactivated.
- it is one year old. The admin of your Chatvia server can change this with
SANCTUM_TOKEN_TTL_MINUTESin the environment file.
A request without a working key gets 401 Unauthorized.
Who a key acts as
A key acts as the person who generated it, with exactly the access that person has in the dashboard.
- The workspace owner's key can call every endpoint.
- A teammate's key can only do what the teammate's role allows. It sees only the agents the role reaches. Roles are set up in Teams & roles. A teammate's key uses the role of the team the teammate has open in the dashboard. When they switch teams there, the key follows.
Some endpoints are for the owner only, whatever a teammate's role says:
- creating an agent
- everything under
/teamsand/users
Each endpoint on the following pages names the permission it needs. The names are the ones you see when you edit a role in the dashboard. In short:
| What you call | Permission a teammate needs |
|---|---|
| Read an agent, its sources, functions, connectors and forms | Access to the agent only |
| Open a conversation and send messages | Access to the agent only |
| Update an agent | Setup agent |
| Delete an agent | Delete agent |
| Add a file, text, website or Q&A pair | Train Files, Train Text, Train Web or Train Q&A |
| Delete a source | Delete sources |
| Attach or detach a function | Manage Functions |
| Attach or detach a connector, change forms | Manage Connectors |
| List and read conversations and messages | View conversations |
| Delete a conversation | Delete conversations |
| Read form submissions | View leads |
| Export form submissions | Export leads |
| List and read eval runs | View evals |
| Start an eval run | Manage evals |
| Topics | Manage topics |
| Analytics | Chat analytics, Sentiment, Tones, Topics or Sources |
| An agent's audit log | View audit log |
| Workspace functions | Functions |
| Workspace connectors | Connectors |
| Chatters and sign-in links | Chatters |
| The prompt library | Prompts |
| The workspace audit log | Governance |
Rate limits
A rate limit caps how many requests you can send in a minute. Chatvia counts per person, so all the keys of one person share one budget.
| Requests | Limit |
|---|---|
| All API requests | 300 a minute |
| Sending a chat message | 30 a minute, on top of the general limit |
| Exporting form submissions as CSV | 10 a minute, shared with exports from the dashboard |
| Starting an eval run | 6 a minute, shared with runs started in the dashboard |
Sending a message has its own, lower limit because every message costs a reply from an AI model.
When you go over a limit, Chatvia answers 429 Too Many Requests:
{
"message": "Too Many Attempts."
}The Retry-After header says how many seconds to wait. Every answer also carries X-RateLimit-Limit and X-RateLimit-Remaining, so you can slow down before you hit the limit. For bulk jobs, such as adding a thousand pages, send a few requests at a time instead of all at once.
Errors
A request that fails gets an HTTP status code and a JSON body with a message. This holds even when you leave out the Accept: application/json header. The API never redirects you to a sign-in page or returns an HTML error page.
| Status | Meaning |
|---|---|
200 OK |
Done. The body holds the result. |
201 Created |
A new record was made. The body holds it. |
204 No Content |
Done. There is no body, for example after a delete. |
401 Unauthorized |
The key is missing, wrong, revoked or expired, or its account is deactivated. |
403 Forbidden |
The key works, but its person may not do this. The permission is missing, the route is owner-only, or the agent is outside the teammate's role. |
404 Not Found |
The record does not exist, belongs to another workspace, or belongs to another agent than the one in the path. A malformed id is a 404 too. |
422 Unprocessable Content |
The request was understood, but a value is wrong or missing. |
429 Too Many Requests |
You went over a rate limit. See above. |
A 401 looks like this:
{
"message": "Unauthenticated."
}A 422 names each field that failed in errors:
{
"message": "The name field is required. (and 1 more error)",
"errors": {
"name": ["The name field is required."],
"is_public": ["The is_public field is required."]
}
}Some refusals that happen after the input checks also come back as a 422 on one field. For example, adding a text your workspace already has:
{
"message": "This text is already in your knowledge base.",
"errors": {
"content": ["This text is already in your knowledge base."]
}
}A few routes answer 404 instead of 403 when the permission is missing, so they don't reveal that the record exists. The prompt library is one of them.
Sending a chat message has a few more error codes of its own. See Send a message.
Pagination
Every list endpoint returns one page of items, newest first, plus a next_cursor:
{
"data": ["…"],
"next_cursor": "eyJpZCI6MTg2LCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9"
}To get the next page, send that value back as the cursor query parameter:
curl "https://chat.example.com/api/v1/agents?cursor=eyJpZCI6MTg2LCJfcG9pbnRzVG9OZXh0SXRlbXMiOnRydWV9" \
-H "Authorization: Bearer $CHATVIA_API_KEY"On the last page next_cursor is null. Stop there.
| Query parameter | Type | Default | Notes |
|---|---|---|---|
per_page |
integer | 25 |
How many items a page holds, from 1 to 100. A value outside that range is brought into range, not refused. |
cursor |
string | none | The next_cursor of the previous page. Leave it out for the first page. |
A cursor marks a place in the list, not a page number. Items added or deleted while you page through don't shift what you get. That is also why there are no page numbers and no total count. Treat the cursor as an opaque string: send back exactly what you received. A cursor that Chatvia did not hand out starts the list again at the first page.
IDs and dates
- Most records are named by a UUID, such as
0199f3a2-7c4e-7b1a-9d2e-5f6a7b8c9d0e. The field is always calledidin responses. - Agents have a shorter id of their own, 14 letters and digits, such as
a3f9c2e17b4d08. It is the same id you see in the agent's chat address and in the embed code (data-agent-id). - An id in the path that is not in the right shape is a
404. - Dates and times are in ISO 8601 with a time zone offset, such as
2026-10-25T09:14:03+00:00. A few fields that hold a day only use2026-10-25.
Interactive reference
Your Chatvia server also publishes a reference that it builds from its own code. Open https://chat.example.com/docs/api in a browser. It lists every endpoint with its fields, and you can send test requests from the page with your key. The same reference is available as an OpenAPI file at https://chat.example.com/docs/api.json, which many tools can import to generate a client.
Both pages are open to anyone who can reach your server, without signing in. They describe the API only. They don't show any of your data.
What the API can't do
Some tasks need a person in the dashboard:
- Training files and websites. A file or website added through the API waits until a teammate clicks Train. Texts start training on their own. See Sources.
- Connecting catalog connectors that sign in with OAuth. They need a browser.
- Approving tool calls. Tools that need a person's approval are not offered to the agent in API conversations.
- Creating eval cases. The API runs the cases you set up on the agent's Evals page.