Overview
The FalaAI API is a set of independent APIs. You do not need to transcribe with FalaAI to diagnose or audit: if you already have the text, send it straight to the analysis (BYOT).
- Key: all routes require Authorization: Bearer fai_<your_key>, except GET/HEAD /v1/health and GET /api/version.
- Zero-storage (LGPD): audio/text/result are processed in memory and discarded.
- Languages: transcription in 31 languages; diagnosis in 21 locales; audit and HTML report in 3 (pt/en/es).
Authentication
What it is for: how to prove who you are on each call.
- Key: every route requires the header Authorization: Bearer fai_<your_key> — except GET/HEAD /v1/health and GET /api/version (public, no key).
- How to get it: create the account and generate the API Key in the Dashboard. The key is shown only once (show-once) — store it safely.
- Scopes: each key has scopes —
transcribe, diagnostic, auditoria, whatsapp, alerts, billing, invoices (or * for all). A route without the required scope → 403 insufficient_scope.
- JWT: besides the
fai_ key, the API accepts a session JWT on the same routes.
Authentication errors
| Code | HTTP | Cause |
invalid_api_key | 401 | Bearer missing or invalid. |
key_expired | 401 | Expired key. |
invalid_token | 401 | JWT missing/invalid/expired. |
insufficient_scope | 403 | The key does not have the scope required by the route. |
Required fields — quick summary
If you just want it to work, these are the fields the API requires on each endpoint:
| Endpoint | Required | Note |
POST /v1/audio/transcriptions | file | mp3, mp4, m4a, wav, flac, ogg, opus, webm, aac · up to 1 GB and 3 hours |
POST /v1/analyze/diagnostic | language + (text or dialog) | one of the two: text (simple) or dialog (with speakers/timestamps) |
POST /v1/analyze/riskAudit | dialog, duration_seconds, language, response_language | audit only accepts diarized content; max duration 3h (10800s) |
POST /v1/whatsapp/extractConversations | file, timezone, date_format (+ start/end outside the preview) | see the accepted values in the endpoint section |
GET/HEAD /v1/health · GET /api/version | — (public, no key) | no fields |
Golden rule of the analyses: input = text (plain transcription) or dialog (who spoke + timestamps). Risk audit requires dialog.
GET /v1/health public
no keymonitoring
What it is for: only to say whether the server is up and the version/uptime/database status. It analyzes nothing.
flowchart LR
A[Monitor / uptime / curl] -->|GET /v1/health| B{{FalaAI API}}
B -->|200| C[status, version, uptime, database]
A2[Light check] -->|HEAD /v1/health| B
B -->|200 without body| D[only the HTTP code]
classDef pub fill:#dcfce7,stroke:#16a34a,color:#14532d
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
class A,A2,C,D pub
class B api
Fields
None.
Request (cURL example)
loading...
Response — fields
| Field | Type | Description |
status | string | Overall API status |
version | string | Current API version |
uptime_seconds | integer | Uptime, in seconds |
database | boolean | Database connection status |
phase | string | Development phase |
launch_date | string | Planned public launch date |
HEAD /v1/health = same 200 without body.
Example response (JSON)
loading...
Possible flows
- Uptime/monitoring (every 1 min) with an alert if != 200.
- Deploy health check (cheaper):
HEAD. - Read the API version for logging.
GET /api/version public
no key
What it is for: identify the contract version in use (pin your client compatibility).
flowchart LR
A[Your client / CI] -->|GET /api/version| B{{FalaAI API}}
B --> C[contract version]
C --> D[Pin/validate compatibility]
classDef pub fill:#dcfce7,stroke:#16a34a,color:#14532d
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
class A,C,D pub
class B api
Fields
None.
Response
| Field | Type | Description |
service | string | Service name |
version | string | Current contract version |
deployDate | string | Deploy timestamp |
POST /v1/audio/transcriptions multipart/form-data
requires fai_text, dialog, audio_events
What it is for: turn audio into text with speaker separation (diarization), timestamps and audio events.
Fields
| Field | Type | Required | What it is / values |
file | file | yes | Audio: mp3, mp4, m4a, wav, flac, ogg, opus, webm, aac · up to 1 GB and 3 hours |
model | string | no | falaai-transcribe-1 (default) |
language | string | no | Forces the audio language (e.g. pt); if omitted, it is detected |
client_reference_id | string | no | Free ID returned in the response (correlation; not idempotency) |
Request (cURL example)
loading...
Response — fields
| Field | Type | Description |
id | string | tr- + UUID |
object | string | sempre transcription |
model | string | Model used |
filename | string | Uploaded file name |
processed_at | string | Processing ISO UTC |
language | string | Detected language (ISO 639-3, e.g. por) |
language_confidence | number | Language detection confidence |
duration_seconds | number | Audio duration |
text | string | Running text |
dialog | string | Turns Speaker N: [HH:MM:SS.mmm - HH:MM:SS.mmm] text |
audio_events[] | array | Events: event, start_s, end_s, duration_s, formatted_timestamp |
event_types[] | array | Detected event types |
word_count | integer | Word count |
input | object | duration_s, original_format, codec, sample_rate, channels |
usage | object | audio_seconds, credits_consumed, processing_ms |
client_reference_id | string | Verbatim echo (if sent) |
Example response (JSON)
loading...
Flow
flowchart TD
S([Do you have the audio?]) -->|yes| U[Choose the file: mp3, mp4, m4a, wav, flac, ogg, opus, webm, aac... up to 1GB / 3h]
U --> T[POST /v1/audio/transcriptions + file]
T --> R[Response: text, dialog, audio_events, duration_seconds, usage]
R --> D1[Use in Diagnostic]
R --> A1[Use in Risk Audit]
R --> DB[(Your database / CRM / BI)]
S -->|no, I already have text| B[Skip: go straight to Diagnostic or Risk Audit]
classDef in fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef out fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95
class S,U,B in
class T api
class R,D1,A1,DB out
Possible flows
- Audio → transcription → diagnosis (summary, reason, action, topic, sentiment).
- Audio → transcription → risk audit (score + violations + report).
- Audio → transcription → (diagnosis + audit) on the same conversation.
- Batch: repeat per file in a queue and consolidate per account/team.
POST /v1/analyze/diagnostic application/json
requires fai_summary, reason, action, topic, sentiment
What it is for: diagnose the conversation — 5 analyses in one call.
Fields
| Field | Type | Required | What it is / values |
language | string | yes | Transcription language: pt-BR, en-US, es-ES, es-MX, fr-FR, de-DE, it-IT, pt-PT... |
dialog | string | one of the two | Primary source: turns with speaker and timestamps (Speaker 1: [00:00:00.100 - ...] ...) |
text | string | one of the two | Plain transcription (used if dialog is empty) |
duration_seconds | number | with dialog | Total audio duration (ignored when there is only text) |
audio_events | array | with dialog | Audio events: {"event":"[sigh]","start_s":3.1,"end_s":4.7} (fields: event required; start_s, end_s, duration_s, formatted_timestamp optional) |
participants | array | no | Explicit roles (if omitted, the AI infers): interlocutor (required) + role = agent | client | bot; name optional |
response_language | string | no | Output language (may differ from the input language) |
call_direction | string | no | inbound (customer called) or outbound (company called); if omitted, the AI infers |
model | string | no | falaai-diagnostic-1 (default) |
client_reference_id | string | no | ID livre devolvido na resposta |
Request (cURL example)
loading...
Response — fields
| Field | Type | Description |
id | string | di- + UUID |
object | string | always analysis |
response_language | string | Language used in the response |
analysis.dialogue_summary | object | { explanation } — dialogue summary |
analysis.contact_reason | object | { explanation } — contact reason |
analysis.identified_action | object | { list_choice, justification, evidence_phrases[] } |
analysis.identified_label | object | { list_choice, justification, evidence_phrases[] } |
analysis.sentiment | object | { list_choice, justification, evidence_phrases[] } |
analysis.participants_identified[] | array | { interlocutor, role, name, confidence, evidence } |
usage | object | { characters, credits_consumed, processing_ms } |
client_reference_id | string | Verbatim echo (if sent) |
html_report | string | base64+gzip; only when there is dialog |
Example response (JSON)
loading...
Flow
flowchart TD
I{How do you have the conversation?} -->|plain transcription| X[text = running transcription + language]
I -->|with who spoke| Y[dialog = turns with speaker and timestamps + language + duration_seconds]
X --> P[POST /v1/analyze/diagnostic]
Y --> P
P --> R[summary, contact_reason, action_taken, topic, sentiment]
R --> O1[Quality / CX dashboard]
R --> O2[CRM / ticket / ERP]
R --> O3[BI / warehouse]
classDef in fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef out fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95
class I,X,Y in
class P api
class R,O1,O2,O3 out
Possible flows
- I already have a transcription (Whisper/Deepgram/own) → just diagnose (BYOT).
- Audio → transcription → diagnosis (full pipeline).
- Diagnosis + audit on the same conversation.
- Batch per conversation and aggregation by period/team (
client_reference_id for tracking).
POST /v1/analyze/riskAudit application/json
requires fai_score + violations + report
What it is for: audit risk/compliance (COPC CX, ISO 18295-1, LGPD): score, detections/violations, evidence and an auditable HTML report.
Required: it only accepts dialog (diarized). With plain text it does not run.
Fields
| Field | Type | Required | What it is / values |
dialog | string | yes | Turns with speaker and timestamps (same format as the diagnosis) |
duration_seconds | number | yes | Total duration; must be >= the end of the last turn; max 3h (10800s) |
language | string | yes | Dialog language (must match the text) |
response_language | string | yes | Output language and HTML report language (pt/en/es) |
response_format | string | no | v2 (default) — the only one available today |
audio_events | array | no | Audio events (same format as the diagnosis) |
participants | array | no | Explicit roles; without them the AI infers |
call_direction | string | no | inbound | outbound |
model | string | no | falaai-risk-audit-1 (default) |
client_reference_id | string | no | ID livre devolvido na resposta |
Request (cURL example)
loading...
Response — fields (inside response)
| Field | Type | Description |
response.meta | object | Identification (id, object, call_duration_s, analyzed_at, client_reference_id) + usage |
response.participants | object | identified[], call_direction, role_inference_reliable, identification_status, unidentified_items_count |
response.verdict | object | label, level_code, risk_matrix, applied_actions[] |
response.scores | object | conversation (consolidated score, density, trend, severity) + per_participant |
response.detections | object | violations[], positives[], client_risk_alerts[], client_behavior_alerts[], client_negatives[] |
response.analysis | object | global_metrics, final_analysis, frameworks (COPC/ISO/Kirkpatrick/CSAT) |
response.timeline | object | turns_sentiment[] (VAD per turn), audio_events[], audio_groups_found[] |
response.audio_event_model | object | MAC semantics of the events + windows_s |
response.categories_summary | object | Catalog by key (category, criticality, scores, terms) |
response.actions_i18n | object | Actions by key (label/description/priority) |
response.indexer | object | suggested_terms_for_bank[] |
response.summary | object | Counts (turns, active, tolerated, events, participants) |
response.audit_decisions | object | Risk origin + zero-tolerance |
response.scoring_explanation | object | Score composition step by step |
response.html_report | string | HTML in base64+gzip |
Example response (JSON)
loading...
Flow
flowchart TD
A{Do I already have the dialog?} -->|yes| P[POST /v1/analyze/riskAudit + dialog + duration_seconds + language + response_language]
A -->|audio only| T[POST /v1/audio/transcriptions] --> P
P --> R[risk score, detections, verdict, summary, usage]
R --> V1[Auditable HTML report]
R --> V2[Audit 100% of the conversations]
R --> V3[Evidence for legal / dispute]
R --> V4[Action plan per team]
classDef in fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef out fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95
class A,T in
class P api
class R,V1,V2,V3,V4 out
Possible flows
- One-off audit: one conversation → score + violations + report.
- Batch audit (100%): all conversations of the day/week → ranking by risk.
- Audit + diagnosis for context (reason/action) together with the risk.
- Re-check after training (compare score before/after).
POST /v1/whatsapp/extractConversations multipart/form-data
requires fai_extracted conversations
What it is for: extract and segment conversations from a WhatsApp export (.zip/.txt) to then diagnose or audit.
Fields
| Field | Type | Required | What it is / values |
file | file | yes | Export: .zip (with media) or .txt (no media). Requires chat.txt in UTF-8 |
timezone | string | yes | Offset from UTC. E.g.: -3 = America/Sao_Paulo (Brazil), +0 = Africa/Abidjan, +5:30 = Asia/Calcutta. Accepts -11 to +14 (15 min steps) |
date_format | string | yes | Date order in the export: day_first (DD/MM/YYYY — Brazil), month_first (MM/DD/YYYY — US) or year_first (YYYY/MM/DD). Any other value → 400 invalid_date_format |
start / end | string | fora do preview | Extraction window, in the date_format format (also accepts ISO YYYY-MM-DD HH:MM). Sentinel 00/00/0000 00:00 (or empty) = whole file |
windows | string | alternativa | Multiple windows: JSON [{"start":"...","end":"..."}] — do not combine with start/end |
dry_run | boolean | nao (default false) | true = FREE PREVIEW: validates, segments and ESTIMATES the credits without calling the AI and without charging |
gap_minutes | number | nao (default 720) | Gap without messages that separates one conversation from another (720 = 12 h) |
min_messages | integer | nao (default 2) | Minimum number of messages for the excerpt to become a conversation |
voice_note | boolean | nao (default true) | Transcribe voice/video messages recorded on the spot |
expression | boolean | nao (default true) | Describe visual expressions (sticker/GIF/image) |
client_reference_id | string | no | ID livre devolvido na resposta |
Request (cURL example, per variant)
Preview (free)
loading...
Single window (extraction)
loading...
Multiple windows (extraction)
loading...
Response — fields
| Field | Type | Description |
object | string | Preview: whatsapp_preview; extraction: conversations |
dry_run | boolean | true in the preview |
credits_charged | number | 0 in the preview |
credits_total | number | Credit estimate |
params | object | Preview: start, end, timezone, date_format, gap_minutes, min_messages, voice_note, expression |
windows[] | array | Preview: detected windows |
items[] | array | Preview: conversation_id, first_at, last_at, duration_minutes, messages, characters, speakers[] |
warnings[] | array | Warnings (preview) |
id | string | Extraction: wc- + UUID |
usage | object | Extraction: conversations, characters, expressions, expressions_figurinha, expressions_gif, expressions_emoji, voice_notes, conversation_credits, expression_credits, audio_credits, credits_consumed, processing_ms |
conversations[] | array | Extraction: conversation_id, first_at, last_at, duration_seconds, speakers[], dialog, message_count, characters |
meta | object | Extraction: file, chat_txt, format, date_format, timezone, start, end, gap_minutes, min_messages, turns, system_lines, conversations_total, conversations_in_window, monologues_dropped, conversations_selected, voice_note, expression, windows |
client_reference_id | string | Verbatim echo (if sent) |
Example response (JSON, per variant)
Preview (free)
loading...
Single window (extraction)
loading...
Multiple windows (extraction)
loading...
Flow (with the 3 variants)
flowchart TD
U[WhatsApp export: .zip or .txt] --> V{Choose the variant}
V -->|free preview| P1[dry_run=true: returns LABELS and previews - does not extract the conversation]
V -->|single window| P2[start + end define 1 window]
V -->|multiple windows| P3[windows = JSON with several windows]
P2 --> C[conversations: dialog, participants, messages, duration]
P3 --> C
C --> J[Use as JSON transcription in the Playground]
C --> D[POST /v1/analyze/diagnostic]
C --> A[POST /v1/analyze/riskAudit]
P1 --> L[Check volume/labels before spending credits]
L --> V
classDef in fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef prev fill:#fef9c3,stroke:#ca8a04,color:#713f12
classDef out fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95
class U,V in
class P1,P2,P3 api
class L prev
class C,J,D,A out
Possible flows
- Check first (free): run
dry_run=true to see how many conversations/labels exist and the credit estimate.
- Extract the whole conversation (
start+end) → diagnose/audit.
- Extract multiple windows (
windows) → diagnose/audit in batch.
- WhatsApp support → conversa extraida → auditoria de risco (compliance).
In the Playground, the Use as JSON transcription button is only enabled when the response brings a conversation with dialog (single/multiple window variants). In the preview variant it does not even appear.
Combined flows (decision tree)
flowchart TD
S([What do you have at hand?]) --> A{Audio?}
A -->|yes| T[Transcription] --> Q{What do you want to know?}
A -->|no, I have text| Q
A -->|no, I have the WhatsApp export| W[Extract WhatsApp] --> Q
Q -->|summary/reason/action/sentiment| D[Diagnostic]
Q -->|risk/compliance/report| R[Risk Audit]
Q -->|both| D2[Diagnostic + Risk Audit]
D --> FIM([Typed JSON for your system])
R --> FIM
D2 --> FIM
classDef in fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef api fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef out fill:#dcfce7,stroke:#16a34a,color:#14532d
class S,W in
class T,D,R,D2 api
class Q,FIM out
Ready-made recipes
| Scenario | Sequence |
| Contact center with recordings | transcriptions → riskAudit (100% of the conversations) |
| I already have a transcription (Whisper etc.) | diagnostic and/or riskAudit (BYOT) |
| WhatsApp support | extractConversations → diagnostic/riskAudit |
| Quality + context | diagnostic (reason/action) + riskAudit (risk) |
| Monitoring | GET/HEAD /v1/health every minute |
Alert webhooks
What it is for: receive subscription/billing/credit notices on your own HTTPS endpoint, without polling the API.
Scope: these are billing/credit/subscription alerts (10 events). There is no "analysis finished" event.
Endpoints
| Method | Path | Scope | Description |
GET | /v1/webhooks?page&limit | alerts ou * | Lists the subscriptions (paginated: page≥1, limit 1..100, default 20). Includes the secret. |
POST | /v1/webhooks | alerts ou * | Creates the subscription. Returns the secret (hex 64). |
PUT | /v1/webhooks/{webhook_id} | alerts ou * | Updates name/url/events/retry_enabled/active. |
DELETE | /v1/webhooks/{webhook_id} | alerts ou * | Removes the subscription. |
Events (10)
subscription.created · avulso.completed · subscription.upgraded · subscription.downgraded · subscription.canceled
credits.low · credits.exhausted · subscription.renewed · subscription.expired · payment.failed
Payload (example)
{
"event": "credits.low",
"data": { "balance_monthly": 12, "balance_avulso": 0, "total": 12, "plan": "starter_api", "plan_name": "Starter API - 90K" },
"timestamp": 1725470000.123
}
Delivery and security
- Signature: every delivery carries the header FalaAI-Signature: t=<unix>,v0=<hmac_sha256(secret, "<t>.<raw body>")>. Validate by recomputing the HMAC with your
secret and comparing it with v0; reject if t is outside the tolerance window (anti-replay).
- Retry:
retry_enabled=false = 1 attempt; true = up to 5 (backoff 2^attempt: 1s, 2s, 4s, 8s). HTTP timeout of 10s per delivery; a response < 500 counts as delivered; after 5 consecutive failures the subscription is auto-disabled (active=false).
Errors
| Code | HTTP | Cause |
invalid_api_key / key_expired / invalid_token | 401 | Bearer missing/invalid/expired. |
insufficient_scope | 403 | Without the alerts/* scope. |
no_fields | 400 | PUT with no field to update. |
| (conflito) | 409 | A webhook already exists for this destination (duplicate URL). |
| (Pydantic) | 422 | Invalid payload (event outside the enum, invalid URL...). |
Creation example:
curl -X POST https://api01-falaai.action.tec.br/v1/webhooks -H "Authorization: Bearer fai_<sua_chave>" -H "Content-Type: application/json" -d '{"name":"Alertas","url":"https://seu-endpoint.com/webhook","events":["credits.low","payment.failed"],"retry_enabled":true}'
Limits and common errors
- 401: key missing/invalid (
Authorization: Bearer fai_...).
- 402 / credits: insufficient balance for the operation.
- 413 / limit: file above 1 GB (or audio above 3 h).
- 422: required field missing or invalid format (e.g. audit without
dialog; WhatsApp without timezone/date_format).
- Public without key: only
GET/HEAD /v1/health and GET /api/version.
Full contract: Swagger · openapi.json · Quickstart · Playground