Call Review API · Contents

Introduction

The Call Review API scores customer calls against your KPIs and runs your own analysis prompts on them. You send a transcript and say which KPIs and prompts to run. For each KPI, the model reads the whole call and returns a score, a tier, the exact quotes it relied on, its reasoning and one improvement.

Every request and response is JSON over HTTPS. Times are UTC in ISO 8601. The model runs on a dedicated machine, and nothing you send leaves it.

An analysis runs in the background: create it, then read it back when it's done, or let us post it to your server. Try it in the Playground with your token.

Base URLhttps://talksens-ai.tailfb3537.ts.net
Quick start
# 1. Send a call with the KPIs to score
curl https://talksens-ai.tailfb3537.ts.net/v1/analyses \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"transcript": "Agent: ...\nCustomer: ...",
       "kpi_ids": ["kpi_3f2a9c1d0b7e4a5f6c8d"]}'

# 2. Read it back when status is "done"
curl https://talksens-ai.tailfb3537.ts.net/v1/analyses/an_9b1c0d2e3f4a5b6c7d8e \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"

Authentication

The API uses bearer tokens. Send yours in the Authorization header of every request except Check health.

Keep the token on your servers: never in a mobile app, a browser or source control. Load it from an environment variable or a secret store.

Each token comes with a webhook secret, used only to check that a callback really came from us. Both are given to you once, privately. Each team has its own token, and a token sees only its own KPIs and analyses. If a token leaks, tell us: we revoke it and it stops working at once.

Header
Authorization: Bearer YOUR_TOKEN

Errors

Errors use standard HTTP status codes and always have the same body: an error object with a machine-readable code, a human message, and for invalid bodies a list of details.

StatusCodeMeaning
401unauthorizedNo token, a wrong one, or a revoked one.
404not_foundNo such KPI or analysis for your token.
409not_cancellableThe analysis already finished.
411length_requiredA body was sent without Content-Length.
413too_largeThe body is over 1 MB, or the transcript is over 200,000 characters.
422invalid_requestThe body doesn't match the parameters; details names the field.
429rate_limitedMore than 120 requests in a minute. Retry with backoff.
429queue_full500 of your analyses are already waiting.
5xxA problem on our side. Retry with backoff; tell us if it lasts.
Error response
{
  "error": {
    "code": "invalid_request",
    "message": "the request body is not valid",
    "details": [
      {
        "field": "transcript",
        "problem": "Value error, send exactly one of transcript or turns"
      }
    ]
  }
}

Rate limits and timing

The model works on one call at a time and runs that call's KPIs and prompts one after another. Results are saved as each one finishes, so you can read a running analysis and see what's done so far.

LimitValue
Time per KPIAbout 70–120 seconds, depending on the call's length
Requests per token120 per minute
Waiting analyses500 per client
KPIs and prompts per analysis20
Request body1 MB
Transcript200,000 characters. The model reads about 32,000 tokens at once: transcript, KPI and answer together.
Transcripts kept30 days after the analysis finishes. Results are kept.

Polling every 15–30 seconds is plenty. A queued analysis tells you its position and an estimated_wait_seconds.

Create analysis

POST/v1/analyses

Queues one call to be scored against KPIs and analysed with your prompts. It returns at once; the work happens in the background.

Request body

transcriptstringOptional

The call as text, for example Agent: … and Customer: … lines. Send either transcript or turns.

turnsarrayOptional

The call as a list of turns. Written for the model as [time] Speaker: text lines.

Show properties
speakerstringRequired

Who is speaking, for example Agent or Customer.

textstringRequired

What they said.

timestring or numberOptional

When it was said, for example 00:01:12.

kpi_idsarray of stringsOptional

Ids of KPIs you registered with Create KPI.

kpisarrayOptional

One-off KPIs for this call only, in the same shape as the Create KPI body. They are not saved.

promptsarrayOptional

Analysis prompts: any other question about the call.

Show properties
instructionsstringRequired

What to do with the call.

namestringOptional

Your label for the result. Defaults to analysis.

response_format"text" or "json"Optional

Defaults to "text". With "json", the output is parsed JSON.

json_schemaobjectOptional

A JSON Schema the JSON output must follow.

promptstringOptional

Shorthand for one text prompt named analysis.

metadataobjectOptional

Anything you want back with the result, such as your call id or agent id. Up to 10 KB.

callback_urlstringOptional

A public https address we post the finished analysis to. See Callbacks.

Send at least one KPI or prompt, and at most 20 in total.

Returns

A short analysis object with status: "queued", its place in the queue and the expected wait.

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/analyses \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "transcript": "Agent: Thank you for calling...\nCustomer: ...",
    "kpi_ids": ["kpi_3f2a9c1d0b7e4a5f6c8d"],
    "prompts": [{
      "name": "tags",
      "instructions": "Give the call reason and outcome.",
      "response_format": "json"
    }],
    "metadata": {"call_id": "C-10293"}
  }'
Response202
{
  "id": "an_9b1c0d2e3f4a5b6c7d8e",
  "status": "queued",
  "position": 2,
  "estimated_wait_seconds": 330,
  "items": [
    {"type": "kpi", "name": "Upselling", "kpi_id": "kpi_3f2a9c1d0b7e4a5f6c8d"},
    {"type": "prompt", "name": "tags"}
  ],
  "created_at": "2026-10-26T09:20:11Z"
}

Retrieve analysis

GET/v1/analyses/{analysis_id}

Returns an analysis with its status and every result finished so far.

Path parameters

analysis_idstringRequired

The id from Create analysis.

Returns

The analysis object.

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/analyses/an_9b1c0d2e3f4a5b6c7d8e \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"
Response200
{
  "id": "an_9b1c0d2e3f4a5b6c7d8e",
  "status": "done",
  "model": "talksens-1.1",
  "created_at": "2026-10-26T09:20:11Z",
  "started_at": "2026-10-26T09:23:40Z",
  "finished_at": "2026-10-26T09:25:31Z",
  "metadata": {"call_id": "C-10293"},
  "items": [ ... ],
  "results": [
    {
      "type": "kpi",
      "name": "Upselling",
      "kpi_id": "kpi_3f2a9c1d0b7e4a5f6c8d",
      "status": "done",
      "score": 8,
      "undefined": false,
      "tier": "Strong",
      "key_evidence": ["Now that we've sorted out your issue, ..."],
      "reasoning": "The agent resolved the issue first, then ...",
      "improvement_suggestion": "Ask one question about usage ...",
      "checks": { ... },
      "timing": {"model": "talksens-1.1", "seconds": 74.2, "prompt_tokens": 1630, "output_tokens": 1162, "stop": "stop"},
      "raw": "1. Score: 8\n2. Tier: Strong\n..."
    }
  ],
  "error": null
}

List analyses

GET/v1/analyses

Your recent analyses, newest first. Each entry is a short summary; read one with Retrieve analysis.

Query parameters

statusstringOptional

Only analyses in this status: queued, running, done, failed or cancelled.

limitintegerOptional

How many to return, 1–200. Defaults to 50.

Returns

An object with an analyses list.

Example request
curl "https://talksens-ai.tailfb3537.ts.net/v1/analyses?status=done&limit=20" \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"
Response200
{
  "analyses": [
    {
      "id": "an_9b1c0d2e3f4a5b6c7d8e",
      "status": "done",
      "created_at": "2026-10-26T09:20:11Z",
      "finished_at": "2026-10-26T09:25:31Z",
      "metadata": {"call_id": "C-10293"},
      "items": 2
    }
  ]
}

Cancel analysis

DELETE/v1/analyses/{analysis_id}

Cancels a queued or running analysis. Results that already finished are kept. A finished analysis returns 409 not_cancellable.

Path parameters

analysis_idstringRequired

The analysis to cancel.

Returns

The id and status: "cancelled".

Example request
curl -X DELETE https://talksens-ai.tailfb3537.ts.net/v1/analyses/an_9b1c0d2e3f4a5b6c7d8e \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"
Response200
{"id": "an_9b1c0d2e3f4a5b6c7d8e", "status": "cancelled"}

The analysis object

One call and everything run on it.

idstring

Starts with an_.

statusstring

queued, running, done, failed or cancelled. An analysis is done when at least one item finished; failed means every item failed.

modelstring

The model that reads your calls: talksens-1.1.

positioninteger

Only while queued: its place in line, counting the analysis that's running.

estimated_wait_secondsinteger

Only while queued: a rough wait, at about 110 seconds per KPI ahead of it.

itemsarray

What was asked, in order: type (kpi or prompt), name, and kpi_id for saved KPIs.

resultsarray

One KPI result or prompt result per item, in the same order, added as each finishes.

metadataobject

What you sent.

callbackobject

If you gave a callback_url: the url and its delivery status.

created_at, started_at, finished_atstring

UTC times, or null until they happen.

errorstring or null

Set only when the whole analysis failed.

OBJECTThe analysis object
{
  "id": "an_9b1c0d2e3f4a5b6c7d8e",
  "status": "running",
  "model": "talksens-1.1",
  "created_at": "2026-10-26T09:20:11Z",
  "started_at": "2026-10-26T09:23:40Z",
  "finished_at": null,
  "metadata": {"call_id": "C-10293"},
  "items": [
    {"type": "kpi", "name": "Upselling", "kpi_id": "kpi_3f2a…"},
    {"type": "prompt", "name": "tags"}
  ],
  "results": [ /* the first item, finished */ ],
  "callback": {"url": "https://api.example.com/hooks", "status": null},
  "error": null
}

The KPI result object

One KPI scored on one call. The fields are read from the model's answer, and every quote is checked against the transcript.

scorenumber or null

The score on the KPI's scale, or null when the KPI can't be judged from this call.

undefinedboolean

true when the model answered "undefined".

tierstring

Exceptional, Strong, Adequate, Below Expectations or Critical Failure.

key_evidencearray of strings

The quotes the score rests on.

reasoningstring

Why this tier.

improvement_suggestionstring

One specific thing the employee could do better.

checksobject

What we verified without a judge.

Show properties
quotesarray

Each quote with found_in_transcript, matched word for word with case and punctuation aside.

quotes_not_foundarray

Quotes that are not in the transcript. Treat a result that has any with care.

score_fits_tierboolean or null

Whether the score falls inside its tier's band, for 1–10 KPIs.

score_in_scaleboolean

Whether the score is inside the KPI's scale.

all_sections_presentboolean

Whether the answer had all five parts.

timingobject

model, seconds, prompt_tokens, output_tokens and stop.

rawstring

The model's full answer, for your records.

status, errorstring, object

done, or failed with an error object.

OBJECTThe KPI result object
{
  "type": "kpi",
  "name": "Upselling",
  "kpi_id": "kpi_3f2a9c1d0b7e4a5f6c8d",
  "status": "done",
  "score": 8,
  "undefined": false,
  "tier": "Strong",
  "key_evidence": [
    "Now that we've sorted out your issue, would you be interested in a faster plan?",
    "I've reset your connection and it should be stable now."
  ],
  "reasoning": "The agent resolved the issue first, then tied the upgrade to the customer's need.",
  "improvement_suggestion": "Ask one question about usage before naming the plan.",
  "checks": {
    "all_sections_present": true,
    "score_in_scale": true,
    "score_fits_tier": true,
    "quotes": [
      {"quote": "Now that we've sorted out your issue, ...", "found_in_transcript": true}
    ],
    "quotes_not_found": []
  },
  "timing": {"model": "talksens-1.1", "seconds": 74.2, "prompt_tokens": 1630, "output_tokens": 1162, "stop": "stop"},
  "raw": "1. Score: 8\n2. Tier: Strong\n3. Key Evidence: ..."
}

The prompt result object

One analysis prompt run on one call.

namestring

The prompt's name.

outputstring, object or null

The answer as text, or as parsed JSON for response_format: "json" (null if the model didn't give valid JSON).

checks.valid_jsonboolean

For JSON prompts: whether the output parsed.

timing, raw, status, error

As in the KPI result object.

OBJECTThe prompt result object
{
  "type": "prompt",
  "name": "tags",
  "status": "done",
  "output": {"reason": "Billing inquiry", "outcome": "Late fee waived"},
  "checks": {"valid_json": true},
  "timing": {"model": "talksens-1.1", "seconds": 17.0, "prompt_tokens": 702, "output_tokens": 211, "stop": "stop"},
  "raw": "{\"reason\": \"Billing inquiry\", ...}"
}

Create KPI

POST/v1/kpis

Saves a KPI so you can run it on calls by id. See Writing a KPI.

Request body

namestringRequired

Up to 200 characters.

instructionsstringRequired

The full evaluator prompt, up to 50,000 characters.

scaleobjectOptional

min and max. Defaults to {"min": 1, "max": 10}; used to check scores are in range.

Returns

The KPI object, with status 201.

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/kpis \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Upselling",
       "instructions": "You are an evaluator analyzing a transcript for ..."}'
Response201
{
  "id": "kpi_3f2a9c1d0b7e4a5f6c8d",
  "name": "Upselling",
  "instructions": "You are an evaluator analyzing a transcript for ...",
  "scale": {"min": 1, "max": 10},
  "created_at": "2026-10-26T09:14:02Z",
  "updated_at": "2026-10-26T09:14:02Z"
}

List KPIs

GET/v1/kpis

Your saved KPIs, oldest first.

Returns

An object with a kpis list of KPI objects.

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/kpis \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"
Response200
{"kpis": [{"id": "kpi_3f2a9c1d0b7e4a5f6c8d", "name": "Upselling", ...}]}

Retrieve KPI

GET/v1/kpis/{kpi_id}

Returns one saved KPI.

Path parameters

kpi_idstringRequired

The KPI's id.

Returns

The KPI object.

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/kpis/kpi_3f2a9c1d0b7e4a5f6c8d \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"

Update KPI

PUT/v1/kpis/{kpi_id}

Replaces a KPI's name, instructions and scale. The new version applies to analyses created after the change; an analysis already created keeps the KPI as it was.

Request body

The same fields as Create KPI.

Returns

The updated KPI object.

Example request
curl -X PUT https://talksens-ai.tailfb3537.ts.net/v1/kpis/kpi_3f2a9c1d0b7e4a5f6c8d \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Upselling v2", "instructions": "..."}'

Delete KPI

DELETE/v1/kpis/{kpi_id}

Deletes a saved KPI. Past analyses that used it keep their results.

Returns

The id and deleted: true.

Example request
curl -X DELETE https://talksens-ai.tailfb3537.ts.net/v1/kpis/kpi_3f2a9c1d0b7e4a5f6c8d \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"
Response200
{"id": "kpi_3f2a9c1d0b7e4a5f6c8d", "deleted": true}

The KPI object

An evaluator prompt you run on calls.

idstring

Starts with kpi_.

namestring

Your name for it.

instructionsstring

The evaluator prompt.

scaleobject

min and max.

created_at, updated_atstring

UTC times.

OBJECTThe KPI object
{
  "id": "kpi_3f2a9c1d0b7e4a5f6c8d",
  "name": "Upselling",
  "instructions": "You are an evaluator analyzing a transcript for ...",
  "scale": {"min": 1, "max": 10},
  "created_at": "2026-10-26T09:14:02Z",
  "updated_at": "2026-10-26T09:14:02Z"
}

Callbacks

Give an analysis a callback_url and we POST it there when it finishes: the same JSON as Retrieve analysis, up to three tries. The address must be public https.

Check the signature before you trust the body. Each callback carries these headers:

X-CallReview-Analysisheader

The analysis id.

X-CallReview-Timestampheader

Unix seconds when it was sent.

X-CallReview-Signatureheader

sha256= followed by the hex HMAC-SHA256 of timestamp + "." + raw body, keyed with your webhook secret.

Answer with any 2xx quickly. If every try fails, the result is still there to read.

Verify a callback
import hmac, hashlib, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    ts = headers["X-CallReview-Timestamp"]
    if abs(time.time() - int(ts)) > 300:
        return False
    mac = hmac.new(secret.encode(), ts.encode() + b"." + raw_body,
                   hashlib.sha256).hexdigest()
    return hmac.compare_digest("sha256=" + mac,
                               headers["X-CallReview-Signature"])

List samples

GET/v1/samples

The sample call and KPIs the Playground offers. They are your own material, so they are only returned to a valid token.

Returns

An object with transcripts (id, name, text) and kpis (id, name, instructions, scale).

Example request
curl https://talksens-ai.tailfb3537.ts.net/v1/samples \
  -H "Authorization: Bearer $CALL_REVIEW_TOKEN"

Check health

GET/v1/health

Whether the service and the model are up, and how many analyses are waiting. Needs no token.

Response200
{
  "status": "ok",
  "version": "1.0.0",
  "model": "talksens-1.1",
  "model_loaded": true,
  "queue": {"queued": 0, "running": 0}
}

Writing a KPI

A KPI's instructions are the model's brief, and the call follows as the transcript. Results are read from the model's answer, so end every KPI with the output block on the right, word for word.

9–10Exceptional
7–8Strong
5–6Adequate
3–4Below Expectations
1–2Critical Failure
  • Keep each KPI to one behaviour. Three focused KPIs score better than one broad one.
  • Describe each score band with example phrases, and list positive and negative signals.
  • Ask for exact quotes. We check each one against the transcript and flag any that aren't there.
  • Say when to answer "undefined": calls where the behaviour never comes up.
  • Judge the employee, not the outcome. Don't penalise them for policy, systems or the customer's own behaviour.
  • Label the speakers in the transcript (Agent: and Customer:), or send turns.
End every KPI with
OUTPUT:
1. Score: [1-10 or "undefined"]
2. Tier: [Exceptional / Strong / Adequate / Below Expectations / Critical Failure]
3. Key Evidence: [3-5 exact transcript quotes that most influenced the score]
4. Reasoning: [2-3 sentences explaining why this tier was chosen]
5. Improvement Suggestion: [1 specific, actionable recommendation]

Return only the structured output above. Do not add any additional commentary, lines, or formatting.