Allerto API

Calls and campaigns

Place a call

POST /v1/calls
Authorization: Bearer alt_live_…
Idempotency-Key: invoice-42

{
  "agent": "7d1c…",
  "to": "+393331234567",
  "inputs": { "name": "Luca Galli", "amount": 250, "month": "January" },
  "reference": "invoice-42",
  "scheduled_at": "2026-10-01T09:30:00+02:00",
  "max_attempts": 2,
  "callback_url": "https://your-app.example/allerto/outcomes"
}
FieldRequiredMeaning
agentyesA published outbound agent
toyesE.164 number
inputswhen the agent requires themValidated against the agent's inputs
referencenoYour id; returned in every event
scheduled_atnoEarliest time for the first attempt
max_attemptsnoOverrides calling.maxAttempts (1–5)
callback_urlnoHTTPS URL receiving this call's events instead of the agent's webhook

The response is 202 with the call object. Repeating the request with the same Idempotency-Key returns 200 and the same call: it is never dialled twice.

What happens next

  1. The queue waits for scheduled_at and for the agent's calling window (Italian time).
  2. It checks the do-not-call list, the daily cap (3 attempts per number per day across the account) and the account's concurrent calls (3 by default).
  3. The phone rings from the agent's caller ID. Answering machines are detected and hung up before the model speaks (voicemail, never retried).
  4. No answer or busy: another attempt after 15 minutes, 1 hour, 3 hours, up to max_attempts. You receive call.attempt_failed for each.
  5. After a conversation the transcript is turned into the agent's result, the outcome is classified and call.completed is sent.
  6. do_not_call adds the number to your list. callback_requested with a time creates a new call at that time (inside the window) when calling.autoCallback is on; it links back with retry_of.

Cancel a call that has not started with POST /v1/calls/{id}/cancel.

The call object

{
  "id": "…",
  "object": "call",
  "direction": "outbound",
  "livemode": true,
  "agent": { "id": "…", "version": 3, "name": "Payment reminder" },
  "client": { "id": "…", "external_id": "default" },
  "campaign_id": null,
  "reference": "invoice-42",
  "to": "+393331234567",
  "from": "+390280781047",
  "inputs": { "name": "Luca Galli", "amount": 250, "month": "January" },
  "status": "completed",
  "outcome": "completed",
  "attempts": 1,
  "max_attempts": 3,
  "next_attempt_at": null,
  "answered_at": "…",
  "ended_at": "…",
  "duration_seconds": 94,
  "callback_at": null,
  "transfer": null,
  "tool_calls": [],
  "ai_disclosed": true,
  "recording": null,
  "anonymized_at": null,
  "result": {
    "data": { "answer": "will_pay", "pay_by": "2026-10-05" },
    "issues": [],
    "summary": "…",
    "sentiment": {
      "label": "negative",
      "score": -1,
      "start": -2,
      "end": 0,
      "trend": "improving",
      "emotions": [
        {
          "type": "frustration",
          "intensity": "high",
          "evidence": "it's the third time I've called"
        }
      ]
    }
  },
  "retry_of": null,
  "error": null,
  "created_at": "…"
}

Inbound calls have the same shape with direction: "inbound", from set to the caller and no inputs.

Status: queued → dialing → in_progress → processing → completed; or failed, cancelled; needs_review while an operator checks the data (inbound agents with missing data).

Outcome:

OutcomeAnsweredRetriedMeaning
completedyesnoThe conversation reached its purpose (whatever the answer)
callback_requestedyesautomatic, see callback_atAsked to be called later
wrong_personyesnoSomeone else answered
refusedyesnoDid not want to talk
do_not_callyesneverAsked not to be called again
hung_upyesnoEnded before saying anything useful
transferredyesnoHanded to the operator of the agent's transfer settings
no_answer, busynoyes
voicemailnonoAnswering machine
suppressednonoNumber on the do-not-call list
invalid_number, failed, cancellednono

Transfer

A call handed to an operator has outcome: "transferred" and:

"transfer": {
  "to": "+390212345678",
  "status": "answered",
  "requested_at": "…",
  "ended_at": "…",
  "duration_seconds": 184
}

status is requested or dialing while the operator's phone rings, then answered, no_answer, busy or failed; duration_seconds is the time spent with the operator. call.completed is sent as soon as the data collected before the transfer is ready, usually while the transfer is still going on: read the call for its final status. The conversation with the operator is not transcribed.

Sentiment

Every call where the person spoke comes with result.sentiment, for every agent and without configuration, like the summary.

It is read from what the person said, never from their voice: it is text analysis, not emotion recognition from biometric data. sentiment is null when the person did not speak or the call could not be analysed; test-mode calls carry a neutral sentiment.

Reading calls

GET /v1/calls?direction=outbound&outcome=callback_requested&since=2026-09-01T00:00:00Z&limit=50
GET /v1/calls/{id}
GET /v1/calls/{id}/transcript
GET /v1/calls/{id}/recording

ai_disclosed says whether the agent stated it is an AI in its first words (null when it never spoke). recording is { "url": "/v1/calls/{id}/recording" } when the agent records calls: a mono 8 kHz WAV. After 24 months personal data is removed and anonymized_at is set; see Privacy.

Lists are newest first; pass next_cursor as cursor for the next page. Filters: direction, agent, campaign, status, outcome, reference, since.

Campaigns

POST /v1/campaigns
{
  "agent": "7d1c…",
  "name": "January instalments",
  "contacts": [
    { "to": "+393331234567", "inputs": { "name": "Luca Galli", "amount": 250, "month": "January" }, "reference": "A-1" },
    { "to": "+393339876543", "inputs": { "name": "Anna Verdi", "amount": 90, "month": "January" }, "reference": "A-2" }
  ],
  "max_concurrent": 3
}

Every contact is validated before anything is queued: if one is invalid you get 400 invalid_contacts with the index of each problem, and nothing is queued. Duplicates and numbers on the do-not-call list are skipped and reported in skipped. Up to 5,000 contacts per request.

allerto campaigns create --agent <id> --csv contacts.csv --name "January instalments"

The CSV needs a to column (also phone, telefono, numero); reference is optional; every other column is an input. Commas or semicolons both work, and Italian numbers like 333 1234567 become +393331234567.

GET /v1/campaigns/{id} returns counts by_status and by_outcome. pause, resume and cancel are POST /v1/campaigns/{id}/<action>; cancelling cancels the calls still queued.

Do-not-call list

GET    /v1/suppressions
POST   /v1/suppressions        {"number": "+393331234567", "reason": "Asked by email"}
DELETE /v1/suppressions/%2B393331234567

The list is checked when a call is queued and again right before dialling. Adding a number fails its queued calls with suppressed.