Описания endpoints и полей показаны на английском языке, ровно так, как их публикует API. Это наш выбор: здесь вы читаете то же, что увидите в ответах.
GET /v1/feedback#
List answer feedback. One page of the raw feedback rows your visitors and reviewers left on individual answers, in key order (call, then turn, then author). This is also the export: follow the cursor to the end and you hold every row.
**Paging.** Pass the next_cursor from the previous response back as ?cursor=. **An empty next_cursor is the only signal that you have seen everything**, a short page, including an empty one, is normal and means "ask again": the agent filter is applied after each read, so a page can match nothing and still have more behind it.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
call_id |
query |
string |
|
Only one call's feedback. |
agent |
query |
string |
|
Only one agent's feedback. Applied after the read, short pages are normal. |
limit |
query |
integer |
|
Rows per page, 1 to 100 (default 50). Larger values are capped rather than refused. |
cursor |
query |
string |
|
The next_cursor from the previous page. Omit for the first page. A cursor belongs to the scope that issued it. |
Ответы
| Код |
Описание |
200 |
Success. |
400 |
limit is not a positive whole number (bad_request), or cursor was not issued by this listing for this scope (invalid_cursor), start again without it. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl "https://api.voiceland.ai/v1/feedback" \
-H "Authorization: Bearer VL_API_KEY"
Успешный ответ возвращает FeedbackListResponse.
Пример ответа
{
"items": [
{
"agent_name": "front-desk",
"author_id": "widget-user-1a2b",
"author_kind": "visitor",
"call_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
"category": "inaccurate",
"rating": "down",
"rating_kind": "thumbs",
"score": 1,
"tenant_slug": "acme",
"turn_id": "t3",
"turn_role": "agent"
}
],
"next_cursor": ""
}
POST /v1/feedback#
Rate an answer. Records your review of one transcript turn. Send **either** rating (up/down) **or** score (1 to 5), a thumb is stored as 5/1 on the same scale, so both controls land in one shape.
turn_id is t<index>, the zero-based position of the turn in GET /calls/{id}/transcript, or o<offset_ms>, the turn's offset_ms. The turn must exist on the persisted call.
**One row per (turn, author): re-submitting replaces your previous rating, it is never counted twice.** Pass author to keep two reviewers' ratings distinct.
A rating on a human reply (a representative's turn) is stored with its role and deliberately excluded from the agent satisfaction numbers, it is not an AI quality signal.
Тело запроса
application/json Схема: FeedbackSubmitRequest
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
author |
string |
|
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
rating |
string |
|
|
score |
integer |
|
|
turn_id |
string |
Да |
|
Ответы
| Код |
Описание |
200 |
The stored feedback row (replacing any earlier one by the same author on the same turn). |
401 |
Missing or invalid API key. |
404 |
No CDR for that call id (call_not_found), or the turn id names no turn of it (turn_not_found). |
422 |
Neither a rating nor a score was sent, they contradict each other, or the category is not one of inaccurate/outdated/irrelevant/inappropriate/other (invalid_feedback). |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl -X POST "https://api.voiceland.ai/v1/feedback" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"call_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
"category": "outdated",
"comment": "Quotes the 2024 price list.",
"score": 2,
"turn_id": "t3"
}'
Пример ответа
{
"agent_name": "front-desk",
"author_id": "operator",
"author_kind": "operator",
"call_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
"category": "outdated",
"rating": "down",
"rating_kind": "scale",
"score": 2,
"tenant_slug": "acme",
"turn_id": "t3",
"turn_role": "agent"
}
GET /v1/feedback/analytics#
Answer satisfaction analytics. Per-agent satisfaction over the stored feedback rows: rated count, up/down split, average score and the satisfaction rate (share of ratings with score ≥ 4), plus the worst-rated turns as a review feed.
Only ratings on AI turns count; ratings on human replies are excluded and reported in human_turns_excluded. The fold reads a bounded number of rows and says so: when truncated is true the numbers cover scanned rows, not the whole history.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
agent |
query |
string |
|
Fold one agent only. |
Ответы
| Код |
Описание |
200 |
Success. |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl "https://api.voiceland.ai/v1/feedback/analytics" \
-H "Authorization: Bearer VL_API_KEY"
Успешный ответ возвращает FeedbackAnalyticsResponse.
Пример ответа
{
"human_turns_excluded": 2,
"items": [
{
"agent": "front-desk",
"average_score": 4.1,
"down": 8,
"rated": 41,
"satisfaction_rate": 0.8,
"up": 33
}
],
"scanned": 43,
"truncated": false,
"worst": [
{
"agent": "front-desk",
"call_id": "widget-8c2f…",
"category": "inaccurate",
"rating": "down",
"score": 1,
"turn_id": "t3"
}
]
}
GET /v1/feedback/regressions#
Export confirmed-wrong answers (regression cases). Every report resolved confirmed_wrong, as stable rows an evaluation harness can consume: the snapshotted answer, its sources, the linked knowledge document and the resolution trail. Rows whose call was erased under a data-subject request keep only the hashed call linkage (erased: true).
**Paging.** Pass the next_cursor back as ?cursor=; **an empty next_cursor is the only signal that the export is complete**, the status filter runs after each read, so short pages with a cursor are normal. The row shape is additive-only: fields may be added, never renamed or removed.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
limit |
query |
integer |
|
Rows per page, 1 to 100 (default 50). |
cursor |
query |
string |
|
The next_cursor from the previous page. Omit for the first page. |
Ответы
| Код |
Описание |
200 |
Success. |
400 |
limit is not a positive whole number (bad_request), or the cursor was not issued by this listing (invalid_cursor). |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl "https://api.voiceland.ai/v1/feedback/regressions" \
-H "Authorization: Bearer VL_API_KEY"
Успешный ответ возвращает FeedbackRegressionsResponse.
Пример ответа
{
"items": [
{
"agent": "front-desk",
"answer_text": "Our premium plan costs …",
"call_id_hash": "b1946ac9…",
"category": "inaccurate",
"id": "fbr_9d8c7b6a",
"kb_document_id": "doc_4b1e77a0",
"resolved_by": "maria@acme.example",
"turn_id": "t3"
}
],
"next_cursor": ""
}
GET /v1/feedback/reports#
List inaccuracy reports (review queue). One page of the reported answers, in report-id order. ?status=open is the review queue; the three resolved states are the history.
Each report carries its own **snapshot** of the answer text and the sources that grounded it, taken when the report was filed, so the review works even after the call itself was erased. snapshot_source says whether the copy came from the stored transcript or was claimed by the reporter mid-session.
**Paging.** Pass the next_cursor back as ?cursor=. **An empty next_cursor is the only signal that you have seen everything**, the status filter runs after each read, so short and empty pages with a cursor are normal.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
status |
query |
string |
|
Filter: open, confirmed_wrong, correct or fixed. Applied after the read. |
limit |
query |
integer |
|
Rows per page, 1 to 100 (default 50). |
cursor |
query |
string |
|
The next_cursor from the previous page. Omit for the first page. |
Ответы
| Код |
Описание |
200 |
Success. |
400 |
status is not one of the four states or limit is not a positive whole number (bad_request); or the cursor was not issued by this listing (invalid_cursor). |
401 |
Missing or invalid API key. |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl "https://api.voiceland.ai/v1/feedback/reports" \
-H "Authorization: Bearer VL_API_KEY"
Успешный ответ возвращает FeedbackReportsResponse.
Пример ответа
{
"items": [
{
"answer_text": "Our premium plan costs …",
"call_id": "widget-8c2f…",
"category": "inaccurate",
"id": "fbr_9d8c7b6a",
"snapshot_source": "transcript",
"sources": [
{
"chunk_id": "doc_4b1e77a0:0003",
"document_id": "doc_4b1e77a0",
"index": 1,
"title": "Τιμολόγηση 2026"
}
],
"status": "open",
"turn_id": "t3"
}
],
"next_cursor": ""
}
POST /v1/feedback/reports#
Report an inaccurate answer. Files one answer into the review queue. The answer text and the sources that grounded it are **copied from the stored transcript turn at this moment**, never recomputed later, so the report stays reviewable even if the call is erased afterwards.
turn_id is t<index> (transcript item index) or o<offset_ms>, and must name a turn of the persisted call.
Тело запроса
application/json Схема: FeedbackReportCreateRequest
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
author |
string |
|
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
turn_id |
string |
Да |
|
Ответы
| Код |
Описание |
201 |
The report, open, with the snapshot attached. |
401 |
Missing or invalid API key. |
404 |
No CDR for that call id (call_not_found), or the turn id names no turn of it (turn_not_found). |
422 |
The category is not one of inaccurate/outdated/irrelevant/inappropriate/other (invalid_feedback). |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl -X POST "https://api.voiceland.ai/v1/feedback/reports" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"call_id": "widget-8c2f1a7e-4b3d-4e21-9c0a-5f6d7e8a9b0c",
"category": "inaccurate",
"comment": "The quoted price is last year'\''s.",
"turn_id": "t3"
}'
Пример ответа
{
"answer_text": "Our premium plan costs …",
"call_id": "widget-8c2f…",
"category": "inaccurate",
"id": "fbr_9d8c7b6a",
"snapshot_source": "transcript",
"status": "open",
"turn_id": "t3"
}
GET /v1/feedback/reports/{id}#
Get an inaccuracy report. One report, snapshot included.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
id |
path |
string |
Да |
Report id. |
Ответы
| Код |
Описание |
200 |
Success. |
401 |
Missing or invalid API key. |
404 |
No report with that id (report_not_found). |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl "https://api.voiceland.ai/v1/feedback/reports/{id}" \
-H "Authorization: Bearer VL_API_KEY"
Пример ответа
{
"category": "inaccurate",
"id": "fbr_9d8c7b6a",
"status": "open",
"turn_id": "t3"
}
POST /v1/feedback/reports/{id}/resolve#
Resolve an inaccuracy report. Records the review decision: confirmed_wrong (the answer is wrong and becomes a regression case, see GET /feedback/regressions), correct (the answer was fine), or fixed (you corrected the knowledge content, so the expected answer changed). Optionally link the knowledge document that caused it with kb_document_id.
**confirmed_wrong with a kb_document_id flags that document for review**: it appears in GET /kb/review-flags with a pointer back to this report, and its cited_wrong_count goes up. kb_document_flagged in the response says whether that happened. It is false when no document was named or the document no longer exists, and the decision itself is recorded either way.
**A decision is one-shot**: resolving an already-resolved report answers 409.
Параметры
| Имя |
Место |
Тип |
Обязательно |
Описание |
id |
path |
string |
Да |
Report id. |
Тело запроса
application/json Схема: FeedbackResolveRequest
| Поле |
Тип |
Обязательно |
Описание |
kb_document_id |
string |
|
|
note |
string |
|
|
resolution |
string |
Да |
|
resolved_by |
string |
|
|
Ответы
| Код |
Описание |
200 |
The resolved report. |
401 |
Missing or invalid API key. |
404 |
No report with that id (report_not_found). |
409 |
The report is already resolved (already_resolved). |
422 |
resolution is not confirmed_wrong, correct or fixed (invalid_resolution). |
4XX |
Request error (validation, not-found, etc.). |
5XX |
Server or upstream error. |
Пример запроса
curl -X POST "https://api.voiceland.ai/v1/feedback/reports/{id}/resolve" \
-H "Authorization: Bearer VL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"kb_document_id": "doc_4b1e77a0",
"note": "Doc quotes the 2024 price list.",
"resolution": "confirmed_wrong",
"resolved_by": "maria@acme.example"
}'
Успешный ответ возвращает FeedbackResolveResponse.
Пример ответа
{
"id": "fbr_9d8c7b6a",
"kb_document_flagged": true,
"kb_document_id": "doc_4b1e77a0",
"status": "confirmed_wrong"
}
Схемы#
AnswerFeedback#
| Поле |
Тип |
Обязательно |
Описание |
agent_name |
string |
|
|
author_id |
string |
Да |
|
author_kind |
string |
Да |
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
created_at |
string (date-time) |
|
|
rating |
string |
Да |
|
rating_kind |
string |
Да |
|
score |
integer |
Да |
|
tenant_slug |
string |
Да |
|
turn_id |
string |
Да |
|
turn_role |
string |
Да |
|
updated_at |
string (date-time) |
|
|
AnswerFeedbackReport#
| Поле |
Тип |
Обязательно |
Описание |
agent_name |
string |
|
|
answer_text |
string |
|
|
call_id |
string |
|
|
call_id_hash |
string |
Да |
|
category |
string |
Да |
|
comment |
string |
|
|
created_at |
string (date-time) |
|
|
erased |
boolean |
|
|
id |
string |
Да |
|
kb_document_id |
string |
|
|
reporter_id |
string |
|
|
reporter_kind |
string |
Да |
|
resolution_note |
string |
|
|
resolved_at |
string (date-time) |
|
|
resolved_by |
string |
|
|
snapshot_source |
string |
Да |
|
sources |
array of TranscriptSource |
|
|
status |
string |
Да |
|
tenant_slug |
string |
Да |
|
turn_id |
string |
Да |
|
turn_role |
string |
|
|
updated_at |
string (date-time) |
|
|
Error#
Error envelope returned for non-2xx responses.
| Поле |
Тип |
Обязательно |
Описание |
error |
object |
Да |
|
FeedbackAgentAnalytics#
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
Да |
|
average_score |
number |
Да |
|
down |
integer |
Да |
|
rated |
integer |
Да |
|
satisfaction_rate |
number |
Да |
|
up |
integer |
Да |
|
FeedbackAnalyticsResponse#
FeedbackListResponse#
| Поле |
Тип |
Обязательно |
Описание |
items |
array of AnswerFeedback |
Да |
|
next_cursor |
string |
Да |
|
FeedbackRegressionCase#
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
answer_text |
string |
|
|
call_id |
string |
|
|
call_id_hash |
string |
Да |
|
category |
string |
Да |
|
erased |
boolean |
|
|
id |
string |
Да |
|
kb_document_id |
string |
|
|
note |
string |
|
|
reported_at |
string (date-time) |
Да |
|
resolved_at |
string (date-time) |
Да |
|
resolved_by |
string |
|
|
sources |
array of TranscriptSource |
|
|
turn_id |
string |
Да |
|
FeedbackRegressionsResponse#
FeedbackReportCreateRequest#
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
author |
string |
|
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
turn_id |
string |
Да |
|
FeedbackReportsResponse#
FeedbackResolveRequest#
| Поле |
Тип |
Обязательно |
Описание |
kb_document_id |
string |
|
|
note |
string |
|
|
resolution |
string |
Да |
|
resolved_by |
string |
|
|
FeedbackResolveResponse#
| Поле |
Тип |
Обязательно |
Описание |
agent_name |
string |
|
|
answer_text |
string |
|
|
call_id |
string |
|
|
call_id_hash |
string |
Да |
|
category |
string |
Да |
|
comment |
string |
|
|
created_at |
string (date-time) |
|
|
erased |
boolean |
|
|
id |
string |
Да |
|
kb_document_flagged |
boolean |
Да |
|
kb_document_id |
string |
|
|
reporter_id |
string |
|
|
reporter_kind |
string |
Да |
|
resolution_note |
string |
|
|
resolved_at |
string (date-time) |
|
|
resolved_by |
string |
|
|
snapshot_source |
string |
Да |
|
sources |
array of TranscriptSource |
|
|
status |
string |
Да |
|
tenant_slug |
string |
Да |
|
turn_id |
string |
Да |
|
turn_role |
string |
|
|
updated_at |
string (date-time) |
|
|
FeedbackSubmitRequest#
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
author |
string |
|
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
rating |
string |
|
|
score |
integer |
|
|
turn_id |
string |
Да |
|
FeedbackWorstItem#
| Поле |
Тип |
Обязательно |
Описание |
agent |
string |
|
|
call_id |
string |
Да |
|
category |
string |
|
|
comment |
string |
|
|
rating |
string |
Да |
|
score |
integer |
Да |
|
turn_id |
string |
Да |
|
TranscriptSource#
| Поле |
Тип |
Обязательно |
Описание |
chunk_id |
string |
Да |
|
document_id |
string |
Да |
|
index |
integer |
Да |
|
title |
string |
|
|
url |
string |
|
|