Submit feedback and corrections for a prior API query
POST /v1/feedback
Help shape Arcmira. Report a wrong result, request sources or capabilities, or tell us what would make your workflow more useful. To correct a result, attach corrections to the exact query you ran: pass the feedback type, the query object you sent, and optional per-item corrections. Public submissions are recorded for human review (status "logged"); nothing is auto-applied. Read the review status back later via GET /v1/feedback/{feedback_id}. recommendations and channel_sponsors feedback types require a Pro+ plan; every other type needs read. monitor_alert feedback targets fired alerts: query carries monitor_id and/or tracker_id and/or alert_id, corrections target the alert id, and every referenced alert must belong to the caller (otherwise 404 alert_not_found). missed_alert corrections are expectations with nothing to target: omit the correction id and put { source_url, approximate_timestamp_seconds?, entity_id? } in suggested_change. delivery_issue corrections may carry { channel } in suggested_change. experience feedback says how a task went as a whole rather than correcting a result: it requires category and notes, refuses corrections (400 invalid_feedback_request), and needs no query. category and mcp_call_id, when sent, are recorded in the stored query.
Parameters
| Name | Location | Description |
|---|
| type | query | Feedback type when omitted from the JSON body. Provide type in either location; the body takes precedence. |
| query | query | Query being reviewed when omitted from the JSON body. Body query fields override matching query-string fields. |
| Idempotency-Key | header | 1 to 255 printable ASCII characters (0x21 to 0x7E); anything else is 400 invalid_idempotency_key. Persist a unique key and the exact request before sending a logical mutation. A retry returns its stored response with Idempotency-Replayed: true. A changed intent under a finalized key returns 409 idempotency_conflict. Keys belong to the authenticated owner, credential and mutation domain. Current authorization still applies. Receipts have no general 24-hour expiry; signing-secret recovery alone expires after 24 hours or when the secret is displaced. |
Request body
{
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"recommendations",
"channel_sponsors",
"mentions",
"entities_search",
"entities",
"channels",
"monitor_alert",
"appearances",
"search",
"experience"
],
"description": "The surface being reviewed. Values: recommendations (/v1/recommendations results by com_* id; requires a Pro+ plan), channel_sponsors (sponsor entities on a channel; requires a Pro+ plan), mentions (/v1/mentions results by men_* id), entities_search (/v1/entities/resolve candidates), entities (/v1/entities/{id} payloads), channels (/v1/channels/{channel_id}/videos results), monitor_alert (fired alerts from /v1/monitors/{id}/alerts or /v1/trackers/{id}/alerts; corrections target the alert id), appearances (person appearances from /v1/mentions with is_appearance=true), search (/v1/search passages), experience (how a task went as a whole, not one result: requires category and notes, takes no corrections, and query is optional)."
},
"query": {
"type": "object",
"additionalProperties": {},
"description": "The query object that produced the result you are reviewing, echoed back verbatim so reviewers can replay it. For monitor_alert feedback, carry monitor_id and/or tracker_id and/or alert_id."
},
"endpoint": {
"type": "string",
"maxLength": 500
},
"method": {
"type": "string",
"enum": [
"GET",
"POST",
"PATCH",
"PUT",
"DELETE"
]
},
"request_id": {
"type": "string",
"maxLength": 200
},
"result_url": {
"type": "string",
"maxLength": 2000
},
"source_url": {
"type": "string",
"maxLength": 2000
},
"notes": {
"type": "string",
"maxLength": 4000,
"description": "Free text for the reviewer. Required when type is experience: say what the user asked for and what went wrong, slow, or missing."
},
"corrections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Public id of the result being corrected, from the response you received: men_* (mentions, appearances), com_* (recommendations), ent_* (entities, sponsors), or the alert id (monitor_alert). Omit for missed_alert and missing_result corrections, which have nothing to target."
},
"class": {
"type": "string",
"enum": [
"sponsored",
"organic",
"mention"
],
"description": "On recommendations feedback, the class the result should carry. Values: sponsored (an ad-style promotion heard at that moment: a paid sponsor read, promo code, affiliate plug, thanks for supplied goods or venue, or a show promoting its own product as an ad), organic (an unpaid personal recommendation), mention (a neutral commercial mention)."
},
"reason": {
"type": "string",
"enum": [
"false_positive_ad_read",
"false_positive_endorsement",
"missed_ad_read",
"missed_endorsement",
"wrong_classification",
"wrong_entity",
"other"
]
},
"issue_type": {
"type": "string",
"enum": [
"wrong_entity_type",
"wrong_entity",
"duplicate_entity",
"merge_suggestion",
"missing_result",
"stale_metadata",
"wrong_classification",
"bad_ranking",
"false_positive_alert",
"wrong_media",
"wrong_timestamp",
"duplicate_alert",
"missed_alert",
"delivery_issue",
"person_not_present",
"wrong_person",
"wrong_appearance_role",
"other"
],
"description": "Issue classification for the correction. Entity-family values: wrong_entity_type (right entity, wrong type), wrong_entity (the result points at the wrong canonical entity), duplicate_entity (results split across variants of the same entity), merge_suggestion (propose the canonical merge for split variants), missing_result (a result you know should exist is absent), stale_metadata (name/website/channel metadata is outdated), wrong_classification (class-level error on a commercial result), bad_ranking (duplicates or aliases ranking above the canonical entity). monitor_alert values: false_positive_alert (the alert should not have fired), wrong_media (fired against the wrong video), wrong_timestamp (fired at the wrong position in the video), duplicate_alert (the same occurrence fired more than once), missed_alert (an expectation: an alert that should have fired but did not; nothing to target), delivery_issue (the delivery itself was wrong: wrong channel, not received). appearances values: person_not_present (the person does not appear in the media), wrong_person (the appearance is attributed to the wrong person), wrong_appearance_role (right person, wrong role, e.g. guest vs host). other (escape hatch; detail in notes)."
},
"suggested_change": {
"anyOf": [
{
"$ref": "#/components/schemas/MergeSuggestionChange"
},
{
"$ref": "#/components/schemas/WrongEntityChange"
},
{
"$ref": "#/components/schemas/WrongEntityTypeChange"
},
{
"$ref": "#/components/schemas/MissingResultChange"
},
{
"$ref": "#/components/schemas/WrongClassificationChange"
},
{
"$ref": "#/components/schemas/StaleMetadataChange"
},
{
"$ref": "#/components/schemas/BadRankingChange"
},
{
"$ref": "#/components/schemas/MissedAlertChange"
},
{
"$ref": "#/components/schemas/DeliveryIssueChange"
},
{
"$ref": "#/components/schemas/FreeformSuggestedChange"
}
],
"description": "Your concrete proposed fix, shaped by issue_type: merge_suggestion → MergeSuggestionChange, wrong_entity/wrong_person → WrongEntityChange, wrong_entity_type → WrongEntityTypeChange, missing_result → MissingResultChange, wrong_classification → WrongClassificationChange, stale_metadata → StaleMetadataChange, bad_ranking → BadRankingChange, missed_alert → MissedAlertChange, delivery_issue → DeliveryIssueChange. Unknown keys are accepted and logged verbatim; only non-object values are rejected. Omit suggested_change entirely when you do not have a concrete fix."
},
"notes": {
"type": "string",
"maxLength": 2000
}
}
},
"maxItems": 100,
"description": "Per-result corrections. Not allowed when type is experience."
},
"category": {
"type": "string",
"enum": [
"wrong_entity",
"bad_data",
"missing",
"slow",
"confusing",
"other"
],
"description": "What kind of problem this is. Values: wrong_entity (a name resolved to the wrong person, company or thing), bad_data (a result or field is wrong), missing (something that should exist was not found), slow (the task took too long), confusing (the answer or an error was hard to act on), other (anything else; say what in notes). Required when type is experience."
},
"mcp_call_id": {
"type": "string",
"pattern": "^mcpc_[0-9a-f]{32}$",
"description": "The MCP tool call this feedback is about, as the Arcmira MCP server names it (mcpc_ and 32 hex digits). Joins the feedback to that call in product analytics."
}
}
}
}
}
}
Responses
200 Success
{
"description": "Success",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"RateLimit-Limit": {
"$ref": "#/components/headers/RateLimit-Limit"
},
"RateLimit-Remaining": {
"$ref": "#/components/headers/RateLimit-Remaining"
},
"RateLimit-Reset": {
"$ref": "#/components/headers/RateLimit-Reset"
},
"Idempotency-Replayed": {
"$ref": "#/components/headers/Idempotency-Replayed"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeedbackResponse"
}
}
}
}
400 InvalidRequest
{
"$ref": "#/components/responses/InvalidRequest"
}
401 AuthenticationError
{
"$ref": "#/components/responses/AuthenticationError"
}
403 PermissionError
{
"$ref": "#/components/responses/PermissionError"
}
404 NotFound
{
"$ref": "#/components/responses/NotFound"
}
409 Conflict. idempotency_conflict means the Idempotency-Key was finalized with a different request intent.
{
"description": "Conflict. idempotency_conflict means the Idempotency-Key was finalized with a different request intent.",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
429 RateLimited
{
"$ref": "#/components/responses/RateLimited"
}
500 ServerError
{
"$ref": "#/components/responses/ServerError"
}
Operation definition
{
"tags": [
"Feedback"
],
"operationId": "submit_feedback",
"summary": "Submit feedback and corrections for a prior API query",
"description": "Help shape Arcmira. Report a wrong result, request sources or capabilities, or tell us what would make your workflow more useful. To correct a result, attach corrections to the exact query you ran: pass the feedback type, the query object you sent, and optional per-item corrections. Public submissions are recorded for human review (status \"logged\"); nothing is auto-applied. Read the review status back later via GET /v1/feedback/{feedback_id}. recommendations and channel_sponsors feedback types require a Pro+ plan; every other type needs read. monitor_alert feedback targets fired alerts: query carries monitor_id and/or tracker_id and/or alert_id, corrections target the alert id, and every referenced alert must belong to the caller (otherwise 404 alert_not_found). missed_alert corrections are expectations with nothing to target: omit the correction id and put { source_url, approximate_timestamp_seconds?, entity_id? } in suggested_change. delivery_issue corrections may carry { channel } in suggested_change. experience feedback says how a task went as a whole rather than correcting a result: it requires category and notes, refuses corrections (400 invalid_feedback_request), and needs no query. category and mcp_call_id, when sent, are recorded in the stored query.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"schema": {
"type": "string",
"enum": [
"recommendations",
"channel_sponsors",
"mentions",
"entities_search",
"entities",
"channels",
"monitor_alert",
"appearances",
"search",
"experience"
],
"description": "Feedback type when omitted from the JSON body. Provide type in either location; the body takes precedence."
},
"required": false,
"description": "Feedback type when omitted from the JSON body. Provide type in either location; the body takes precedence.",
"name": "type",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"description": "Query being reviewed when omitted from the JSON body. Body query fields override matching query-string fields."
},
"required": false,
"description": "Query being reviewed when omitted from the JSON body. Body query fields override matching query-string fields.",
"name": "query",
"in": "query"
},
{
"schema": {
"type": "string"
},
"required": false,
"name": "Idempotency-Key",
"in": "header",
"example": "8b2f6c3e-4d1a-4e7b-9c05-2f6a1b7d3e90",
"description": "1 to 255 printable ASCII characters (0x21 to 0x7E); anything else is 400 invalid_idempotency_key. Persist a unique key and the exact request before sending a logical mutation. A retry returns its stored response with Idempotency-Replayed: true. A changed intent under a finalized key returns 409 idempotency_conflict. Keys belong to the authenticated owner, credential and mutation domain. Current authorization still applies. Receipts have no general 24-hour expiry; signing-secret recovery alone expires after 24 hours or when the secret is displaced."
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"recommendations",
"channel_sponsors",
"mentions",
"entities_search",
"entities",
"channels",
"monitor_alert",
"appearances",
"search",
"experience"
],
"description": "The surface being reviewed. Values: recommendations (/v1/recommendations results by com_* id; requires a Pro+ plan), channel_sponsors (sponsor entities on a channel; requires a Pro+ plan), mentions (/v1/mentions results by men_* id), entities_search (/v1/entities/resolve candidates), entities (/v1/entities/{id} payloads), channels (/v1/channels/{channel_id}/videos results), monitor_alert (fired alerts from /v1/monitors/{id}/alerts or /v1/trackers/{id}/alerts; corrections target the alert id), appearances (person appearances from /v1/mentions with is_appearance=true), search (/v1/search passages), experience (how a task went as a whole, not one result: requires category and notes, takes no corrections, and query is optional)."
},
"query": {
"type": "object",
"additionalProperties": {},
"description": "The query object that produced the result you are reviewing, echoed back verbatim so reviewers can replay it. For monitor_alert feedback, carry monitor_id and/or tracker_id and/or alert_id."
},
"endpoint": {
"type": "string",
"maxLength": 500
},
"method": {
"type": "string",
"enum": [
"GET",
"POST",
"PATCH",
"PUT",
"DELETE"
]
},
"request_id": {
"type": "string",
"maxLength": 200
},
"result_url": {
"type": "string",
"maxLength": 2000
},
"source_url": {
"type": "string",
"maxLength": 2000
},
"notes": {
"type": "string",
"maxLength": 4000,
"description": "Free text for the reviewer. Required when type is experience: say what the user asked for and what went wrong, slow, or missing."
},
"corrections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Public id of the result being corrected, from the response you received: men_* (mentions, appearances), com_* (recommendations), ent_* (entities, sponsors), or the alert id (monitor_alert). Omit for missed_alert and missing_result corrections, which have nothing to target."
},
"class": {
"type": "string",
"enum": [
"sponsored",
"organic",
"mention"
],
"description": "On recommendations feedback, the class the result should carry. Values: sponsored (an ad-style promotion heard at that moment: a paid sponsor read, promo code, affiliate plug, thanks for supplied goods or venue, or a show promoting its own product as an ad), organic (an unpaid personal recommendation), mention (a neutral commercial mention)."
},
"reason": {
"type": "string",
"enum": [
"false_positive_ad_read",
"false_positive_endorsement",
"missed_ad_read",
"missed_endorsement",
"wrong_classification",
"wrong_entity",
"other"
]
},
"issue_type": {
"type": "string",
"enum": [
"wrong_entity_type",
"wrong_entity",
"duplicate_entity",
"merge_suggestion",
"missing_result",
"stale_metadata",
"wrong_classification",
"bad_ranking",
"false_positive_alert",
"wrong_media",
"wrong_timestamp",
"duplicate_alert",
"missed_alert",
"delivery_issue",
"person_not_present",
"wrong_person",
"wrong_appearance_role",
"other"
],
"description": "Issue classification for the correction. Entity-family values: wrong_entity_type (right entity, wrong type), wrong_entity (the result points at the wrong canonical entity), duplicate_entity (results split across variants of the same entity), merge_suggestion (propose the canonical merge for split variants), missing_result (a result you know should exist is absent), stale_metadata (name/website/channel metadata is outdated), wrong_classification (class-level error on a commercial result), bad_ranking (duplicates or aliases ranking above the canonical entity). monitor_alert values: false_positive_alert (the alert should not have fired), wrong_media (fired against the wrong video), wrong_timestamp (fired at the wrong position in the video), duplicate_alert (the same occurrence fired more than once), missed_alert (an expectation: an alert that should have fired but did not; nothing to target), delivery_issue (the delivery itself was wrong: wrong channel, not received). appearances values: person_not_present (the person does not appear in the media), wrong_person (the appearance is attributed to the wrong person), wrong_appearance_role (right person, wrong role, e.g. guest vs host). other (escape hatch; detail in notes)."
},
"suggested_change": {
"anyOf": [
{
"$ref": "#/components/schemas/MergeSuggestionChange"
},
{
"$ref": "#/components/schemas/WrongEntityChange"
},
{
"$ref": "#/components/schemas/WrongEntityTypeChange"
},
{
"$ref": "#/components/schemas/MissingResultChange"
},
{
"$ref": "#/components/schemas/WrongClassificationChange"
},
{
"$ref": "#/components/schemas/StaleMetadataChange"
},
{
"$ref": "#/components/schemas/BadRankingChange"
},
{
"$ref": "#/components/schemas/MissedAlertChange"
},
{
"$ref": "#/components/schemas/DeliveryIssueChange"
},
{
"$ref": "#/components/schemas/FreeformSuggestedChange"
}
],
"description": "Your concrete proposed fix, shaped by issue_type: merge_suggestion → MergeSuggestionChange, wrong_entity/wrong_person → WrongEntityChange, wrong_entity_type → WrongEntityTypeChange, missing_result → MissingResultChange, wrong_classification → WrongClassificationChange, stale_metadata → StaleMetadataChange, bad_ranking → BadRankingChange, missed_alert → MissedAlertChange, delivery_issue → DeliveryIssueChange. Unknown keys are accepted and logged verbatim; only non-object values are rejected. Omit suggested_change entirely when you do not have a concrete fix."
},
"notes": {
"type": "string",
"maxLength": 2000
}
}
},
"maxItems": 100,
"description": "Per-result corrections. Not allowed when type is experience."
},
"category": {
"type": "string",
"enum": [
"wrong_entity",
"bad_data",
"missing",
"slow",
"confusing",
"other"
],
"description": "What kind of problem this is. Values: wrong_entity (a name resolved to the wrong person, company or thing), bad_data (a result or field is wrong), missing (something that should exist was not found), slow (the task took too long), confusing (the answer or an error was hard to act on), other (anything else; say what in notes). Required when type is experience."
},
"mcp_call_id": {
"type": "string",
"pattern": "^mcpc_[0-9a-f]{32}$",
"description": "The MCP tool call this feedback is about, as the Arcmira MCP server names it (mcpc_ and 32 hex digits). Joins the feedback to that call in product analytics."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Success",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"RateLimit-Limit": {
"$ref": "#/components/headers/RateLimit-Limit"
},
"RateLimit-Remaining": {
"$ref": "#/components/headers/RateLimit-Remaining"
},
"RateLimit-Reset": {
"$ref": "#/components/headers/RateLimit-Reset"
},
"Idempotency-Replayed": {
"$ref": "#/components/headers/Idempotency-Replayed"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeedbackResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/InvalidRequest"
},
"401": {
"$ref": "#/components/responses/AuthenticationError"
},
"403": {
"$ref": "#/components/responses/PermissionError"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Conflict. idempotency_conflict means the Idempotency-Key was finalized with a different request intent.",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/ServerError"
}
}
}