# Security and data handling

This page describes how API access is protected and how call data available through the API (transcripts, recordings, analysis and contact data) is handled. For what you should do in your own integration, see [Security practices](/fundamentals/security-practices).

## Access control

- **Scoped keys.** Every key is limited to the scopes chosen when it was created, and never does more than the member who created it may do right now. A creator who leaves the workspace takes the key's access with them. Keys cannot change workspace settings, compliance settings, members, billing or other keys.
- **Expiring keys.** Live keys always expire (30 to 365 days). Rotation keeps the old key working only for the grace period you choose; revocation is immediate.
- **Keys are shown once** and the console only ever shows a prefix and the last four characters afterwards.
- **One workspace, one mode.** A key reads and changes only its own workspace's data, in its own mode. Ids from another workspace or from the other mode answer [`resource_not_found`](/errors/resource_not_found), so a request cannot even learn whether they exist.
- **Test and live separated.** Test mode never dials, charges or touches live data, and test data is invisible to live keys.
- **No live keys in browsers.** A live key sent from a browser is refused before it is checked ([`live_key_not_allowed_in_browser`](/errors/live_key_not_allowed_in_browser)).
- **IP allowlist.** Workspaces can restrict API access to their own addresses in the console security settings ([`ip_not_allowed`](/errors/ip_not_allowed)).
- **Fails closed.** When the API cannot complete an access check, it refuses the request ([`service_unavailable`](/errors/service_unavailable)) rather than letting it through.
- **Attributed.** Every API request is attributed to the key that made it, and the console shows each key's last use and recent request counts.
- **HTTPS only**, for the API, recording links and webhook deliveries.

## Data in API responses

Responses return your workspace's data **in full** to keys of that workspace: phone numbers as stored, contact names and custom fields, verbatim transcripts and call analysis. The API does not mask it, because your systems need the real values to act on them. Protect it in your systems accordingly: restrict which keys have `transcripts:read`, `recordings:read` and `contacts:read`, and which people can read what those keys fetch.

Error messages never include personal data, internal details or stack traces.

## Recordings

- Recordings are reached through short-lived links: [`GET /calls/{call_id}/recording`](/api/recordings#retrieve-a-call-recording-link) returns a fresh `url` that works for about 15 minutes (`expires_at`).
- The link itself is the credential: it needs no API key. Anyone with the link can download the audio until it expires, so do not log, store or forward it.
- A link is tied to the key that obtained it: it stops working (`404`) as soon as that key is revoked or expires, loses `recordings:read`, or its creator leaves the workspace.
- An expired link answers [`media_link_expired`](/errors/media_link_expired); ask for a new one.

## Compliance controls

Calls from the API, campaigns and the console, in test mode and in live mode, pass the same checks: the do-not-call list, consent when the workspace requires it (for numbers that match a contact), calling hours and the per-number daily limit. A call is checked when it is placed; a campaign when it starts and when it resumes, not again while it runs. API keys cannot switch the checks off, and the API refuses to start or resume a campaign whose do-not-call screening was switched off in the console ([`campaign_dnc_override_enabled`](/errors/campaign_dnc_override_enabled)). Removals from the do-not-call list are audited. An agent cannot be published unless its instructions tell the people it calls that they are speaking with an AI.

## Metadata, variables and webhooks

- `metadata` you attach to a call is stored and returned as sent. It is never sent to the person called and never used by the agent. Do not put secrets in it.
- `variables` are passed to the agent for that call and can be spoken in the conversation.
- Webhook events carry the same data as the API (for example a call snapshot with the phone numbers) and are signed with a secret only you and RelationsAI hold. Webhook deliveries are kept for 30 days for troubleshooting.

## Questions

For security or data-protection questions, including how long call data is kept for your workspace, contact [support@relationsai.com](mailto:support@relationsai.com). To report a suspected vulnerability, put "Security" in the subject and do not include real customer data or live credentials.
