# Core concepts

The API is built around a small set of objects. This page defines each one, how they relate and which identifier prefix it uses, so the rest of the documentation reads naturally.

```text
Workspace (ws_)
├── API keys (key_)                 one mode each: test or live
├── Agents (agent_)                 configured in the console, read by the API
├── Phone numbers (pn_)             the numbers agents call from
├── Contacts (ct_)                  people you call, with consent and custom fields
│   └── Do-not-call entries (dnc_)  numbers your workspace must not call
├── Calls (call_)                   one conversation each: transcript, recording, analysis
├── Campaigns (cmp_)                one agent calling many recipients
│   └── Recipients (rcp_)           a contact in a campaign, with its latest call
└── Webhook endpoints (we_)         where events (evt_) are delivered (wd_)
```

## Workspace (`ws_`)

Your organisation in RelationsAI. Every key, object and charge belongs to one workspace, and nothing is ever shared between workspaces: another workspace's id answers [`resource_not_found`](/errors/resource_not_found). [`GET /workspace`](/api/workspace#retrieve-the-workspace) returns your workspace with its name, timezone, currency, the current key, its `capabilities` (what the API offers this workspace today) and its `limits`.

Inside a workspace, every key works in one **mode**, test or live, and activity data never crosses between modes. Every object says which with `livemode`. See [Environments](/getting-started/environments).

## Agent (`agent_`)

An AI voice agent: what the person called hears and how the conversation goes. Agents are created, configured, published and switched on in the console; a call always uses the agent's published version. The API lists agents, returns one, and checks whether one can place calls right now with [`GET /agents/{agent_id}/readiness`](/api/agents#check-whether-an-agent-can-place-calls), which returns every problem it finds (for example `agent_not_published` or `no_outbound_number`).

`status` is `active`, `paused`, `draft` or `unknown`; only `active` agents can call. Test mode adds the built-in Sample agent.

## Phone number (`pn_`)

A number your workspace calls from, in E.164 format. Numbers are added and assigned to agents in the console. Each lists the agents that call from it (`outbound_agent_ids`) and the agent that answers it (`inbound_agent_id`). A call uses the agent's outbound number unless you choose one with `phone_number_id`.

## Contact (`ct_`)

A person you may call, identified by phone number (unique per workspace and mode), with a name, language, whether they consented to be called (`consent_granted`), whether they are on the do-not-call list (`do_not_call`) and custom field values. When you call a number that matches a contact, the contact's name and custom fields are passed to the agent as call variables. [`POST /contacts/upsert`](/api/contacts#create-or-update-a-contact-by-phone-number) creates or updates a contact by phone number, which is the easiest way to sync from a CRM.

## Do-not-call entry (`dnc_`)

A number your workspace must not call, in that mode. Calls to it are refused with [`dnc_listed`](/errors/dnc_listed), and campaigns leave it out when they start or resume. A campaign that is already running is not screened again: pause and resume it, or stop it, after adding a number. Matching ignores formatting. Each mode has its own list.

## Call (`call_`)

One outbound phone conversation placed by an agent, from the API, the console or a campaign (`source`). A call moves through these statuses:

| `status` | Meaning |
| --- | --- |
| `queued` | Accepted; being placed. `POST /v1/calls` returns the call in this status. |
| `ringing` | Not reported today; see `capabilities.call_ringing_status`. |
| `in_progress` | Connected. |
| `ended` | Finished. `outcome` and `end_reason` say how. |
| `unknown` | The state could not be confirmed for an unusually long time. Never a success. |

`outcome` is `completed` (a conversation took place), `no_response` (answered but nobody spoke, including most voicemail), `no_answer`, `busy`, `failed` or `unknown`. After a call ends, its three **artifacts** become available, each with its own state (`pending`, `ready`, `absent` or `failed`):

- the **transcript**, turn by turn and verbatim;
- the **recording**, through a short-lived link;
- the **analysis**: a summary, the fields the agent extracts, and whether the call met its goal.

When outcome, duration, artifacts and charge are all final, `settled` becomes `true`. Treat a call's `outcome`, `duration_seconds` and `cost` as final only once it is settled.

## Campaign (`cmp_`) and recipient (`rcp_`)

A campaign calls a list of recipients with one agent, a number of calls at a time (`concurrency_limit`) and an optional budget cap. The budget cap pauses the campaign when spend reaches it; it is checked about every 15 minutes, so spend can exceed the cap by the calls placed in that time. Each recipient is a contact in the campaign, with what happened to them in the current or latest run.

| `status` | Meaning |
| --- | --- |
| `draft` | Created, never started. Recipients can be added only now. |
| `running` | Calling recipients. |
| `paused` | No new calls; resume continues the same run. Can also happen automatically, for example when the budget cap is reached. |
| `stopped` | Ended by request. |
| `completed` | The run called every recipient. |
| `failed` | The run ended in failure. |

Every start and resume screens recipients against the do-not-call list, consent and the per-number daily limit; a running campaign is not screened again. `dnc_screening` is `enforced`, or `disabled_in_console` when a person switched do-not-call screening off for that campaign in the console, in which case the API refuses to start or resume it. Campaigns and contacts carry an `ETag` for safe updates (see [Concurrency](/fundamentals/concurrency)).

## Webhook endpoint (`we_`), event (`evt_`) and delivery (`wd_`)

A webhook endpoint is an HTTPS URL on your server that receives events of one mode. An event is a signed JSON notification such as `call.ended`, `call.settled` or `campaign.completed`, carrying a snapshot of the object. A delivery is one event's attempts to reach one endpoint, which you can list and retry. See [Webhooks](/fundamentals/webhooks).

## Identifiers

Ids are strings with a type prefix, at most 64 characters, for example `call_6Vb3Nm8Qw2Er5Ty9Ui4Op7`. Treat them as opaque: store them as strings and do not parse them or build them yourself. Every response also has a request id (`req_...`) in the `X-Request-Id` header. See [Data types](/fundamentals/data-types).
