Mediflo
REST APIBot sessions

Place an outbound bot call

PLACES A REAL PHONE CALL. Dials `phoneNumber` with the bot `botId` NOW — there is no scheduling, no retry ladder and no confirmation step; the partner owns the timing. Calls are only placed between 08:00 and 20:00 in the tenant’s timezone (`OUTSIDE_CALL_WINDOW` otherwise, window echoed in `details`); nothing is queued. `idempotencyKey` is REQUIRED and is what makes a retry safe: the same key never dials twice — a replay returns the existing session with **200** instead of **201**, and the same key with a different bot or number is refused with `IDEMPOTENCY_KEY_REUSED`. The key is consumed the moment the dispatcher accepts the request — even if the call then fails before anyone picks up (`FAILED` when the call never connects, `no_answer`, `voicemail`): a replay returns that session and never re-dials, so calling the same person again needs a NEW key. Every dispatcher-side error carries `details.dispatchId`. Use your own message or notification id. Requires the opt-in scope `bot-calls.write` (no wildcard grants it). The bot needs an outbound phone number (`BOT_NO_OUTBOUND_NUMBER`) and a published configuration (`BOT_NOT_PUBLISHED`); check `GET /bots/{botId}/readiness` → `readyForOutbound`. `context` is rendered into the bot’s prompt, greeting and workflow as `{{reason}}`, `{{message}}`, `{{appointment_date}}`, `{{appointment_time}}`, `{{appointment_doctor_name}}` (from `appointment.staffName`, or its medical alias `doctorName`), `{{appointment_service_name}}`, `{{appointment_location_name}}`, `{{appointment_address}}`, `{{appointment_external_id}}` plus `variables` verbatim; reserved names are refused as a `422 VALIDATION_ERROR` on `context.variables.<name>`. The bot must be switched on (`BOT_INACTIVE` otherwise). The response is the session as accepted by the dispatcher, still `IN_PROGRESS`: the outcome arrives on the `bot_call.completed` webhook (status completed / no_answer / voicemail / failed / stuck, `durationSec`, `outcome`, `links`) and on `GET /bot-sessions/{dispatchId}`. Mid-call actions (reschedule, cancel) are the bot’s own tools, configured on the bot. Sessions placed this way carry `attemptId` `ext-<dispatchId>`. Required scope: `bot-calls.write`.

POST/bot-sessions

Authorization

ApiKeyAuth
AuthorizationBearer <token>

An external API key, sent as Authorization: Bearer mflo_…. Scopes are checked per route; see each operation’s description.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/bot-sessions" \  -H "Content-Type: application/json" \  -d '{    "botId": "58ed41f0-04bf-402f-9853-7143ef7dd5ce",    "phoneNumber": "string",    "idempotencyKey": "string",    "context": {      "reason": "string"    }  }'
{  "data": {    "dispatchId": "a1a7028f-f483-4bbb-b8e5-fe878bddb1ae",    "botId": "58ed41f0-04bf-402f-9853-7143ef7dd5ce",    "botName": "string",    "status": "IN_PROGRESS",    "endReason": "string",    "startedAt": "2019-08-24T14:15:22Z",    "endedAt": "2019-08-24T14:15:22Z",    "durationSec": 0,    "phoneNumber": "string",    "attemptId": "string",    "hasTranscript": true,    "hasRecording": true,    "hasTelemetry": true,    "outcome": {      "property1": null,      "property2": null    },    "links": {      "telemetry": "string",      "transcript": "string",      "recording": "string"    }  }}

List bot sessions GET

A bot session is one dispatch of one bot to one number — NOT a telephony call record. `status` filters on the same derived status the response reports. Required scope: `bot-calls.read`.

Check whether a bot can take calls GET

A checklist assembled from the publish and dispatch preconditions, for the bot’s channels. Three verdicts: `ready` (can serve at all; a chat-only bot also needs its widget), `readyForOutbound` (serves VOICE_OUTBOUND and the phone chain is dispatchable — a chat-only bot is legitimately false; do not bind a number) and `readyForWebChat` (serves WEB_CHAT and the chat widget is bound). `chat_widget_bound` is fixed in the Portal (Settings → Chat widget). When website chat has booking on, `web_chat_booking_widget` and `web_chat_booking_sms` report WEB_CHAT_BOOKING_WIDGET_MISSING and WEB_CHAT_BOOKING_SMS_MISSING; they are informational. `phone_number_attached` verifies the WHOLE outbound chain and is flagged `requiredFor: outbound` only when the bot places calls. `operating_hours_configured`, `workflow_active` and `location_set` are informational. `ai_disclosure` is an informational ADVISORY: it sweeps the prompt, greeting and active workflow for wording that tells the person they are talking to an AI (EU AI Act Article 50). It is a Polish/English keyword heuristic, so `ok: false` means "we could not find one, please confirm" — not a compliance finding. The obligation and the wording belong to the operator; Mediflo neither enforces nor verifies them, and this check never affects any verdict. Required scope: `bots.read`.