Kalba.ai data protection — what we process, what we store, what we never see
Written for security, compliance, and DPO review. It describes the data path of the Kalba.ai voice API in concrete, testable terms: which fields reach us, which are stored, which are dropped, and how that changes with your account's data mode.
Companion documents: the API reference, the in-call data contract your systems host, and the account servicing guide.
Contents
- Two data modes
- What is stored, field by field
- The variables / metadata rule
- Processing roles and subprocessors
- Hosting and location
- Retention and deletion
- API behaviour in minimal mode
- Integrating before the contract is signed
- Caller-facing obligations
- What we ask of you
Two data modes
Every account runs in one of two modes, fixed during provisioning and visible on
GET /v1/ping so your integration can assert it.
standard | minimal | |
|---|---|---|
| Call audio stored | Yes, retrievable via API | Never fetched or stored |
| Transcript stored | Yes | Never written |
| Automated conversation analysis | Yes (summary, sentiment, quality, outcome) | Not performed |
| Content-derived call outcome | Yes | No — connection facts only |
call.analyzed event | Fires | Never fires |
| Transcript / analysis / recording endpoints | Available | Return 409 retention_disabled |
| Conversation content at rest with us | Yes | None |
minimal is not a shorter retention period. It is a different processing path: the
conversation content is never written to our database, never uploaded to our storage, and
never sent to an analysis model. There is no copy to expire, export, or leak.
The trade is deliberate and total: with no transcript there is nothing to analyse, so
quality scoring, sentiment, objection detection and content-derived outcomes are
unavailable on a minimal account. Calls still resolve to connection-level facts —
answered or not, duration, failure — and everything you need for content lives in your own
systems, which the agent reads live through
your data endpoints.
What is stored, field by field
For a call placed or received on a minimal account, our database holds exactly this:
| Field | Example | Why |
|---|---|---|
| Counterparty phone number | +37061234567 | Required to place or attribute the call |
| Call id | call_7d20… | Your handle for the call |
| Direction | inbound / outbound | Routing and reporting |
| Status | queued, completed, failed | Lifecycle |
| Timestamps | created, started, ended | Lifecycle and billing |
| Duration | 184 seconds | Billing |
| Answered | true / false | Connection fact |
| Cost | per-call charge | Billing |
Your metadata object | {"case_ref":"A-4411"} | Your correlation data — see below |
And this is what is not written, in any mode:
variables— the per-call values your systems pass for the agent to speak (balances, due dates, contract numbers). They are forwarded to the voice runtime for the duration of the conversation and are never persisted by us.- Names, personal codes, dates of birth, or any identifier you use to verify a caller. Verification happens inside your endpoint; we forward the caller's answer and store neither the answer nor the result beyond the live conversation.
- Anything your endpoints return mid-call. Balances, schedules and statuses pass through to the agent's speech and are not retained.
On a minimal account, add to that list: audio, transcripts, and any analysis derived
from them.
The variables / metadata rule
This is the one rule your developers must internalise, because the two fields look alike and behave oppositely:
variablesare ephemeral. Forwarded to the voice runtime, never stored by us. This is where account data belongs:amount_due,due_date,contract_no.metadatais stored. It is persisted against the call and returned on every read and every webhook. Put correlation identifiers there — your own case or contract reference — and never personal or financial data.
{
"to": "+37061234567",
"variables": { "amount_due": "58.40", "due_date": "2026-08-15" }, // ephemeral
"metadata": { "case_ref": "A-4411" } // stored — ids only
}
If you would be uncomfortable seeing a value in a log line six months from now, it belongs
in variables, not metadata.
Processing roles and subprocessors
Kalba.ai acts as processor; you remain controller. Processing is carried out by us and by a small set of subprocessors, each confined to one role:
| Role | Present in standard | Present in minimal |
|---|---|---|
| Voice runtime — speech recognition and synthesis during the live call | Yes | Yes |
| Telephony carriage | Yes | Yes — or your own carrier, see below |
| Application hosting and database | Yes | Yes |
| Error monitoring (technical diagnostics, no conversation content) | Yes | Yes |
| Speech-to-text transcription of recordings | Yes | Absent |
| Conversation analysis model | Yes | Absent |
Choosing minimal removes the transcription and analysis providers from your data path
entirely — the two that would otherwise process conversation content after the call. For a
regulated controller this is usually the decisive simplification: fewer processors to
assess, fewer transfer mechanisms to paper.
Bring your own carrier. Where you operate your own SIP trunk, telephony carriage stays with your existing provider under your existing contract and leaves our subprocessor list too. Configured during provisioning.
Named register. The current subprocessor register — legal entities, roles, locations and transfer mechanisms — is provided with the Data Processing Agreement, and we notify you of changes with the notice period stated there. Model changes within a named provider are not subprocessor changes; adding or replacing a provider is, and is notified as such.
Hosting and location
The primary application database is hosted in the European Union (Germany). Where a component of the voice path can be pinned to an EU region, your account is provisioned that way; where a provider's regional options affect what we can commit to, that commitment is made explicitly in the DPA rather than implied here.
Retention and deletion
- On a
minimalaccount there is no conversation content to retain — the deletion question reduces to call records: phone number, timestamps, duration, status, cost,metadata. - On a
standardaccount, recordings are retained for 90 days by default; a different retention period is set during provisioning. - Call records are retained for the life of the account unless a shorter schedule is agreed.
- Deletion requests for an identified individual are actioned against the phone number; tell us the number and we remove the call records associated with it.
- Suppression is separate from deletion:
POST /v1/dncstops a number from ever being dialled, and that suppression is deliberately retained — a deleted suppression would silently re-enable calling.
API behaviour in minimal mode
Endpoints that would return conversation content respond 409 with code
retention_disabled, distinct from the *_not_ready codes that mean "retry later":
curl -s $KALBA/v1/calls/call_9a1c.../transcript -H "Authorization: Bearer $KEY"
# → 409 { "error": { "type": "invalid_request", "code": "retention_disabled",
# "message": "This account does not store conversation content." } }
The same applies to /analysis and /recording. analysis_status reads disabled, and
call.analyzed never fires — do not wait on it. Build your post-call flow on
call.completed, which carries the connection facts and your metadata.
Assert your mode at startup rather than assuming it:
curl -s $KALBA/v1/ping -H "Authorization: Bearer $KEY"
# → { "ok": true, "mode": "live", "data_mode": "minimal", "key_prefix": "kalba_live_a1b2c" }
Integrating before the contract is signed
Test-mode keys (kalba_test_) place no telephone calls and process no personal
data. Calls are synthesised, the fixtures are ours, and nothing leaves the sandbox. Your
team can therefore build and finish the entire integration — authentication, scheduling,
webhooks, signature verification, your own data endpoints against our mock — while legal
review and the DPA proceed in parallel.
This matters if your experience is that technical work cannot begin until paperwork
completes. Here it can, because until you use a kalba_live_ key there is no personal data
and no processing to govern.
Caller-facing obligations
- AI disclosure. Every call opens with the agent identifying itself as an AI assistant calling on your behalf, before any substance. Non-configurable, inbound and outbound.
- Recording notice. On a
standardaccount the agent states that the call is recorded. On aminimalaccount no recording is made and the notice is adjusted accordingly during script review — a claim that a call is recorded when it is not is itself a defect. - Identity before disclosure. The agent discloses nothing account-specific until your endpoint returns a verified result. This is enforced in the conversation contract, not left to the model's judgement — see the invariant.
- Calling hours and suppression. Outbound calls respect your provisioned window and the do-not-call list is checked at the moment of dialling, not only when a record is created.
What we ask of you
- Keep account data in
variables, identifiers inmetadata. - Host your data endpoints over TLS and verify our request signature on every call — the scheme and sample code are in the in-call contract.
- Return only what the agent needs to speak. An endpoint that returns a full customer record where a balance would do widens your own exposure for no benefit.
- Tell us the lawful basis for outbound calling, per record. Service calls to your own customers under contract and marketing calls requiring consent are different categories and the platform enforces the distinction.