Getting started
Quickstart
Open a conversation and get a streamed reply, in five minutes and three requests.
By the end of this page you will have had a real conversation with your assistant from the command line.
Before you start#
You need two things from Studio.
A published assistant. Open Assistants, pick one, and check it says Published. A draft answers on the dashboard test drive but not over the API — see why.
An API key. Open API → Keys, click Create key, name it something you will recognise in a log six months from now, and copy the key. It is shown once.
export ZEEVAA_API_KEY="zv_live_…"
export ZEEVAA_ASSISTANT_ID="9f2b1c84-6e3a-4d17-b0c5-2e7a8f41d9b3"The assistant id is on the assistant's own page in Studio, and every id in this documentation is a placeholder — yours will differ.
1. Check the key works#
curl https://studio.zeevaa.ai/api/v1/assistants \
-H "Authorization: Bearer $ZEEVAA_API_KEY"{
"assistants": [
{
"id": "9f2b1c84-6e3a-4d17-b0c5-2e7a8f41d9b3",
"name": "Marina sales desk",
"status": "published",
"channels": { "chat": true, "voice": true },
"has_catalogue": true
}
]
}If this returns 401, the key is wrong or revoked. If it returns an empty list,
the key is valid but its workspace has no assistants.
2. Open a conversation#
A session is the conversation. Open one before you say anything.
curl -X POST \
"https://studio.zeevaa.ai/api/v1/assistants/$ZEEVAA_ASSISTANT_ID/sessions" \
-H "Authorization: Bearer $ZEEVAA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"channel": "chat"}'{
"session_id": "c31f9a70-84b2-4e05-9d6c-1a7f3b2e6d48",
"assistant_id": "9f2b1c84-6e3a-4d17-b0c5-2e7a8f41d9b3",
"greeting": "Hi! How can I help you today?",
"started_at": "2026-08-04T09:14:22.108Z"
}Show greeting as the assistant's first message. It is not a turn and does not
appear in the transcript — it is the opening line you configured in Studio.
export ZEEVAA_SESSION_ID="c31f9a70-84b2-4e05-9d6c-1a7f3b2e6d48"3. Say something#
curl -N -X POST \
"https://studio.zeevaa.ai/api/v1/assistants/$ZEEVAA_ASSISTANT_ID/chat" \
-H "Authorization: Bearer $ZEEVAA_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Zeevaa-Format: sse" \
-d "{\"session_id\": \"$ZEEVAA_SESSION_ID\", \"message\": \"What do you have with two bedrooms under 2M?\"}"-N disables curl's buffering, so you see the reply arrive rather than all at
once when it finishes.
event: message.delta
data: {"text":"We have three"}
event: tool.call
data: {"name":"search_records","input":{"bedrooms":2,"price":{"lte":2000000}}}
event: canvas
data: {"kind":"results","total":3,"records":[{"title":"Marina Villa","data":{"price":1850000}}]}
event: message.delta
data: {" that match — the Marina Villa at 1.85M is the closest."}
event: done
data: {"usage":{"input_tokens":412,"output_tokens":88},"session_id":"c31f9a70-…"}Three things happened, and they are worth separating.
The assistant used a tool. tool.call tells you it decided to search the
catalogue, and with what filters. You do not have to show this, but it is what
makes a "thinking…" state honest rather than decorative.
It found records. The canvas event carries structured data — real fields
you can render as cards, not prose describing them. This is the reason to use
the API rather than embed a chat window.
It answered. The message.delta events are the text, in order.
4. Don't want a stream?#
Send "stream": false and get one JSON body when it is finished.
curl -X POST \
"https://studio.zeevaa.ai/api/v1/assistants/$ZEEVAA_ASSISTANT_ID/chat" \
-H "Authorization: Bearer $ZEEVAA_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"session_id\": \"$ZEEVAA_SESSION_ID\", \"message\": \"And the cheapest?\", \"stream\": false}"{
"message": {
"role": "assistant",
"content": "The Marina Villa at 1.85M is the lowest of the three."
},
"tool_calls": [{ "name": "search_records", "status": "success" }],
"usage": { "input_tokens": 508, "output_tokens": 34 }
}Notice the second message understood "the cheapest" without being told what of. You did not resend the first exchange. The session holds the transcript; your code sends one message at a time.
5. Close it#
curl -X POST \
"https://studio.zeevaa.ai/api/v1/sessions/$ZEEVAA_SESSION_ID/end" \
-H "Authorization: Bearer $ZEEVAA_API_KEY"Ending a session stamps its duration and releases it. If your code never gets the chance — a user closes the tab, a process dies — it will be closed automatically once it goes quiet. Ending it deliberately just makes your transcripts and durations accurate.
What you just built#
POST /sessions once per conversation
POST /chat once per message
POST /sessions/…/end once, at the endEverything else in this documentation is detail on those three, plus voice, transcripts and usage.
Next#
- Streaming — the event formats, and which to choose
- Sessions — lifecycle, visitor details, and what a session actually holds
- Next.js integration — the same thing from a real app