Core resources
Recordings
Upload your own call recordings — your team's calls, not your assistant's — and get the same analysis Bolcho runs on its own calls: sentiment, summary, key points, concerns, a lead score and any structured fields you have defined. Upload a batch, poll it while it processes, then read the aggregate or drill into a single call.
Recordings are not calls. A call is something an assistant did; an uploaded recording is something a person did. They are separate resources so that call counts, costs and durations stay unambiguous — nothing you upload here appears in GET /calls or in your call metrics.
How a batch runs
POST /recordings/batches accepts up to 500 audio files (200 MB each) and returns immediately. Each recording moves through queued → transcribing → analyzing → done, three at a time. A 200-file batch takes minutes: poll GET /recordings/batches/{id} and watch doneCount, failedCount and completedAt.
Two ways to say what to extract
Point at an assistant. Pass agentId and the batch uses that assistant's published Analysis configuration — the same structured schema, summary instruction and success rubric it applies to its own calls. structuredData and successEvaluation then mean exactly the same thing on an upload as on a call.
Or send a template inline. If your extraction lives in your own product rather than on a Bolcho assistant, pass analysisConfig — a JSON object with any of summaryPrompt, structuredSchema (JSON Schema) and outcomes (the labels to classify into, each with a description of what it means). Outcome labels come back on outcome; they answer *what happened*, where a success rubric answers *did it work*, so the two are separate fields and either may be absent.
agentId wins if you send both — one template per batch, never two competing definitions. Send neither and you get summary, sentiment, key points, concerns, next steps and a lead score.
{
"summaryPrompt": "what the patient asked for and how it was left",
"outcomes": [
{ "name": "Booked", "description": "The customer confirmed a slot." },
{ "name": "Call back later", "description": "Asked to be contacted again." },
{ "name": "Not interested" }
],
"structuredSchema": {
"type": "object",
"properties": {
"package": { "type": "string", "description": "Which test package" },
"preferredDay": { "type": "string", "enum": ["Sat", "Sun"] }
}
}
}Failures are normal, and re-runnable
Corrupt files, silent recordings and unsupported codecs are expected in a bulk upload. Each one is stored with status: "failed" and a plain-English failureReason rather than failing the batch. POST /recordings/batches/{id}/retry re-queues every failed recording.
failureReason.Matching a recording to a customer
If the filename contains a phone number — the usual 9876543210_2026-08-04.mp3 shape phone systems export — the digits are stored on phone and matched against your existing customers by their last 10 digits, so a bare local number in a filename still finds the +91… contact a real call created. On a match, contactId is set. A recording never *creates* a customer: a filename cannot tell us the country code, and a guessed one would split a single person across two records.
/recordings/batches calls:writeUpload a batch
Upload audio files as multipart/form-data under the field name `files` (repeat it once per file). Returns the created batch; processing starts immediately in the background.
Body
Send as multipart/form-data , repeating the files field once per file.
Body
| files* | file[] | Audio files. Up to 500 per batch, 200 MB each. MP3/WAV/M4A/OGG and MP4/WebM audio. |
| name | string | Batch name, e.g. "July sales calls". Defaults to a count and date. |
| agentId | uuid | Apply this assistant's Analysis configuration — its structured schema, summary instruction and success rubric. |
| analysisConfig | string | A JSON analysis template, for callers with no assistant to point at: `{ summaryPrompt?, structuredSchema?, outcomes? }`. A string because this is a multipart request. Ignored when `agentId` is given. |
curl -X POST https://api.bolchoai.in/v1/recordings/batches -H "Authorization: Bearer $BOLCHO_API_KEY" \
-F "name=July sales calls" \
-F "agentId=7c9e…" \
-F "files=@call-9876543210.mp3" \
-F "files=@call-9812345678.mp3"Response
The batch, with an empty aggregate — nothing has been analysed yet.
{
"id": "b1f3…",
"name": "July sales calls",
"agentId": "7c9e…",
"totalCount": 2,
"doneCount": 0,
"failedCount": 0,
"analysed": 0,
"estimatedCostUsd": "0.0182",
"costUsd": "0",
"completedAt": null,
"createdAt": "2026-08-04T09:12:44.000Z",
"aggregate": { "sentiment": { "positive": 0, "neutral": 0, "negative": 0 }, "avgBantScore": null, "totalDurationSec": 0, "topConcerns": [] }
}/recordings/batches calls:readList batches
Your upload batches, newest first.
Query parameters
| limit | number | Page size (default 20). |
| offset | number | Rows to skip. |
curl https://api.bolchoai.in/v1/recordings/batches -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{
"data": [ { "id": "b1f3…", "name": "July sales calls", "totalCount": 200, "doneCount": 187, "failedCount": 13, "costUsd": "0.8412", "completedAt": "2026-08-04T09:31:02.000Z", "createdAt": "2026-08-04T09:12:44.000Z" } ],
"total": 1,
"limit": 20,
"offset": 0
}/recordings/batches/{id} calls:readGet a batch
One batch with its aggregate across every analysed recording — the sentiment split, average lead score, total audio analysed, and the concerns raised most often. Poll this while `completedAt` is null.
Path parameters
| id* | uuid | Batch id. |
curl https://api.bolchoai.in/v1/recordings/batches/b1f3… -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{
"id": "b1f3…",
"name": "July sales calls",
"totalCount": 200,
"doneCount": 187,
"failedCount": 13,
"analysed": 187,
"estimatedCostUsd": "0.9100",
"costUsd": "0.8412",
"completedAt": "2026-08-04T09:31:02.000Z",
"aggregate": {
"sentiment": { "positive": 96, "neutral": 61, "negative": 30 },
"avgBantScore": 54,
"totalDurationSec": 91240,
"topConcerns": [ { "concern": "price is too high", "count": 22 }, { "concern": "no weekend slots", "count": 14 } ]
}
}/recordings/batches/{id}/recordings calls:readList recordings in a batch
The individual recordings, oldest first. Filter to review what failed, or to read only the negative calls.
Path parameters
| id* | uuid | Batch id. |
Query parameters
| status | string | `queued`, `transcribing`, `analyzing`, `done` or `failed`. |
| sentiment | string | `positive`, `neutral` or `negative`. |
| limit | number | Page size (default 20). |
| offset | number | Rows to skip. |
curl "https://api.bolchoai.in/v1/recordings/batches/b1f3…/recordings?sentiment=negative" -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{
"data": [
{ "id": "r7a2…", "originalName": "call-9876543210.mp3", "status": "done", "durationSec": 412, "sentiment": "negative", "buyerIntent": "low", "bantScore": 21, "summary": "Customer asked about a full-body package and left when told the weekend slots were full.", "successEvaluation": false, "outcome": "Not interested", "phone": "9876543210", "contactId": "c4d1…", "failureReason": null },
{ "id": "r7a9…", "originalName": "hold-music.mp3", "status": "failed", "failureReason": "No speech was detected in this recording.", "sentiment": null }
],
"total": 30,
"limit": 20,
"offset": 0
}/recordings/{id} calls:readGet a recording
One recording in full: the speaker-labelled transcript, the whole analysis, any extracted fields, and a short-lived URL to play the audio.
Path parameters
| id* | uuid | Recording id. |
curl https://api.bolchoai.in/v1/recordings/r7a2… -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{
"id": "r7a2…",
"batchId": "b1f3…",
"originalName": "call-9876543210.mp3",
"status": "done",
"durationSec": 412,
"language": "hi",
"transcript": "Speaker 0: Bilal Clinic Lab, good morning.\nSpeaker 1: Haan, full body package ka rate kya hai?",
"summary": "Customer asked about a full-body package and left when told the weekend slots were full.",
"sentiment": "negative",
"buyerIntent": "low",
"keyPoints": [ "Asked for full-body package pricing", "Wanted a Sunday slot" ],
"concerns": [ "no weekend slots" ],
"nextSteps": "Call back when Sunday collection slots open and offer the ₹1,499 package.",
"successEvaluation": false,
"outcome": "Not interested",
"bantScore": 21,
"structuredData": { "package": "full body", "preferredDay": "Sunday" },
"phone": "9876543210",
"contactId": "c4d1…",
"audioUrl": "https://…blob.core.windows.net/…?sig=…",
"transcriptionCostUsd": "0.0295",
"analysisCostUsd": "0.0004",
"analyzedAt": "2026-08-04T09:18:10.000Z",
"createdAt": "2026-08-04T09:12:45.000Z"
}/recordings/batches/{id}/retry calls:writeRetry failed recordings
Re-queue every recording in the batch that failed, and start processing again. Returns how many were re-queued.
Path parameters
| id* | uuid | Batch id. |
curl -X POST https://api.bolchoai.in/v1/recordings/batches/b1f3…/retry -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{ "requeued": 13 }/recordings/batches/{id} calls:writeDelete a batch
Delete a batch and every analysis in it. The uploaded audio itself is retained.
Path parameters
| id* | uuid | Batch id. |
curl -X DELETE https://api.bolchoai.in/v1/recordings/batches/b1f3… -H "Authorization: Bearer $BOLCHO_API_KEY"Response
{ "ok": true }