Developer platform · v2

Platform

View as MarkdownAll docs

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:

json
{
  "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:

json
{
  "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:

ScopeWhat it opens
project:readread the key's own project's zero retention (GET /v2/project/retention)
voice:readlist and read agents, voice sessions and chats
voice:writecreate, update and delete agents; start sessions and chats, send chat messages
provider_account:readlist and read provider accounts
provider_account:writesave, probe, rotate and disconnect them
carrier:readcarrier catalogue, connections and numbers
carrier:writeconnect, verify, disconnect; import, attach, update and delete numbers
webhook:readlist endpoints and dead letters
webhook:writecreate, test and disable endpoints (it mints a signing secret)
channel:readlist and read chat channels (Telegram bots, WhatsApp numbers, Instagram accounts)
channel:writeconnect, 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_ended when 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_days or insight_config says.
  • 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.completed has transcript and recordingUrl null, chat events have text null, and transfer and hand-off events have reason null. 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:

bash
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:

bash
curl -sS https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/retention \
  -H "Authorization: Bearer $DVAARIK_TOKEN"
json
{
  "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.

bash
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."

bash
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:

bash
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:

json
{
  "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: true means nothing is left. Stop.
  • progress: true and done: false: call again at once.
  • progress: false and done: false: everything left is in use right now, counted in skipped and by kind in skipped_kinds (conversations_in_use, replies_unfinished, deliveries_owed, test_runs_running, rows_busy). Wait retry_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.