Platform
Projects and keys
Projects#
List projects with GET /v2/projects?limit=25&offset=0 and read one with GET /v2/projects/{project_id}, using an account JWT.
A project response contains id, name, optional external_reference, status, revision, is_default, the voice concurrency, API rate and maximum call-second limits, zero_retention (below) and timestamps.
Create with POST /v2/projects:
{
"name": "Production",
"external_reference": "customer_42"
}The name is required and limited to 120 characters. The reference is optional.
Scoped keys#
Create with POST /v2/api-keys and an account JWT:
{
"name": "Production server",
"project_id": "00000000-0000-0000-0000-000000000000",
"scopes": ["project:read", "voice:read", "voice:write"]
}These eleven scopes exist, spelled exactly this way. An unknown scope is refused with 400, so copy them rather than guessing a plural:
| Scope | What it opens |
|---|---|
project:read | read the key's own project's zero retention (GET /v2/project/retention) |
voice:read | list and read agents, voice sessions and chats |
voice:write | create, update and delete agents; start sessions and chats, send chat messages |
provider_account:read | list and read provider accounts |
provider_account:write | save, probe, rotate and disconnect them |
carrier:read | carrier catalogue, connections and numbers |
carrier:write | connect, verify, disconnect; import, attach, update and delete numbers |
webhook:read | list endpoints and dead letters |
webhook:write | create, test and disable endpoints (it mints a signing secret) |
channel:read | list and read chat channels (Telegram bots, WhatsApp numbers, Instagram accounts) |
channel:write | connect, change, check and disconnect chat channels (it hands over their tokens and secrets) |
Request only the scopes a server actually needs — a key handed to a partner app to start sessions should not also be able to disconnect the carrier account those sessions run on. The API reference names the scope on every machine operation.
The creation response is { "key": { ...safe metadata }, "plaintext": "..." }. Plaintext appears once. List with GET /v2/api-keys?project_id=...; revoke with DELETE /v2/api-keys/{key_id}.
Zero retention#
Switch it on for a project and we store no conversation content for its calls, chats and agent test runs. It is off by default. In the console it is the Zero retention switch on the Projects page, under the selected project.
While it is on:
- Kept: only what billing and your call history need. Each call keeps its ids, times, duration, cost, status, end reason (
agent_endedwhen the agent hung up, never the model's own words), carrier status, counts and speed summary. - Not kept: transcripts, summaries and extracted fields, recording references (your carrier is not asked to record) and tool arguments or results, whatever each agent's
store_transcript,record_calls,retention_daysorinsight_configsays. - Chats: each message is kept for the 24-hour reply window, because the next reply needs it, and then deleted. A reply keeps the names of the tools it called, never what went in or came back.
- Webhooks and live sockets still deliver as configured. What we would have to store to deliver is left out:
call.completedhastranscriptandrecordingUrlnull, chat events havetextnull, and transfer and hand-off events havereasonnull. Call events carry `zeroRetention` to say why. - Agent tests keep their verdicts, counts and tokens, never the chat or a judge's reason (it reads "Reason not kept: zero retention.").
It applies to calls, chats and test runs that start after you turn it on; a call keeps the value it started with. Turning it on does not delete what was stored before: delete stored conversations does.
Read it#
From your server, with a key that has project:read. It reads the key's own project and leaves out who changed it:
curl -sS https://api.developers.dvaarik.com/v2/project/retention \
-H "X-Api-Key: $DVAARIK_API_KEY"From the console door, with your account session, it also says who changed it:
curl -sS https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/retention \
-H "Authorization: Bearer $DVAARIK_TOKEN"{
"project_id": "00000000-0000-0000-0000-000000000000",
"zero_retention": true,
"changed_at": "2026-11-08T11:05:00Z",
"changed_by": { "user_id": "...", "email": "you@example.com", "door": "console" },
"changes": [
{ "zero_retention": true, "at": "2026-11-08T11:05:00Z", "user_id": "...", "email": "you@example.com", "door": "console" }
],
"what_is_kept": "Zero retention is on. For calls admitted from the moment it was turned on we keep no transcript, ..."
}changes holds the newest 50, newest last. what_is_kept says in words what is kept right now; it reads differently when the switch is off.
Turn it on or off#
Only the console door changes it: it is an account decision, not something an application's key can do.
curl -sS -X PUT https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/retention \
-H "Authorization: Bearer $DVAARIK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"zero_retention": true}'Turning it off needs "confirm_turn_off": true. Without it the answer is a 422 whose detail is this sentence, and nothing changes: "Turning zero retention off means new calls and chats can store transcripts, recordings and summaries again, as their agents are set up. Send confirm_turn_off: true to do it."
curl -sS -X PUT https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/retention \
-H "Authorization: Bearer $DVAARIK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"zero_retention": false, "confirm_turn_off": true}'Setting the value it already has changes and records nothing. Every change is recorded with who and when. An archived project answers 409.
What reads show#
A call read (GET .../voice/sessions/{session_id}) and a test run read carry zero_retention and retention_note: "stored nothing: zero retention", or null for one that kept its content. The transcript route answers 404 with "No transcript for this call: it ran under its project's zero retention, so nothing of the conversation was stored".
Delete stored conversations#
The switch never deletes what was stored before. This does, for one project, whether the switch is on or off and in any project state:
curl -sS -X POST https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/stored-conversations/delete \
-H "Authorization: Bearer $DVAARIK_TOKEN"It deletes transcripts; clears call summaries and extracted fields, recording references and hand-off reasons; hands audio we stored before 13 Sep 2026 to the hourly sweep; deletes chat messages (not a reply still being sent) and emptied conversations; clears finished test runs' chats and judges' reasons; and drops the stored bodies of webhooks already delivered or dead. Call records, billing, agents, tests, knowledge bases and call lists stay.
Each call is one bounded pass and answers what that pass did:
{
"transcripts_deleted": 500,
"calls_cleared": 120,
"handoff_reasons_cleared": 0,
"archived_recordings_scheduled": 0,
"chat_messages_deleted": 40,
"chat_conversations_deleted": 6,
"test_runs_cleared": 3,
"webhook_bodies_dropped": 200,
"done": false,
"progress": true,
"skipped": 0,
"skipped_kinds": {},
"retry_after_seconds": null
}done: truemeans nothing is left. Stop.progress: trueanddone: false: call again at once.progress: falseanddone: false: everything left is in use right now, counted inskippedand by kind inskipped_kinds(conversations_in_use,replies_unfinished,deliveries_owed,test_runs_running,rows_busy). Waitretry_after_seconds(60) and call again. After about ten such waits, stop and try later.
The console's Delete stored conversations button on the Projects page runs exactly this loop and shows the running counts. The route allows 60 calls a minute.
Use one project per boundary
Provider secrets stay encrypted and project API keys stay on your server.