API reference
Analyze a selected piece of assistant output against its recorded conversation. Strahl provides two endpoints:
- Attributions: high-level attribution endpoint that identifies the most influential sequences and groups them into excerpts ranked by influence, with the specific influential phrases highlighted.
- Attribution scores: a low-level attribution endpoint that returns precise influence scores for character spans in the original transcript.
For a guided introduction, start with the quickstart.
Attributions endpoint
Section titled “Attributions endpoint”POST https://strahl.ai/api/v1/attributionsAuthorization: Bearer <API_KEY>Content-Type: application/jsonRequest body
Section titled “Request body”Send the recorded conversation, including the assistant output you want to investigate. Each request selects one assistant field and, for text or tool arguments, a character range within it. Preserve the original strings and message order.
Example request
Section titled “Example request”{ "input": { "format": "openai/v1/chat/completions", "data": { "messages": [ { "role": "user", "content": "The access code is 1234." }, { "role": "assistant", "content": "The code is 1234." } ] }, "target": { "ref": { "message_index": 1, "field": "content" }, "span": { "start": 12, "end": 16 } } }}This selects 1234 in the assistant’s answer. Message indexes start at zero;
[12, 16) includes characters 12 through 15.
Fields
Section titled “Fields”Wrap these fields in the top-level input object:
| Field | Required | Description |
|---|---|---|
input.format |
Yes | Use the exact string openai/v1/chat/completions. |
input.data.messages |
Yes | A nonempty array of messages in Chat Completions format, including the assistant output to analyze. |
input.data.tools |
No | Tool definitions from the recorded conversation, when available. |
input.target |
Yes | The assistant field and text range to analyze. See target fields for references and offsets. |
Provide the message array under input.data.messages; a provider response’s
choices array is not accepted. Unknown fields in the request envelope, input,
data, target, reference, and span objects are rejected. Extra provider metadata
inside individual messages and tool definitions is ignored.
Target fields
Section titled “Target fields”Targets must select a field belonging to an assistant message. All indexes
start at zero; supply an index explicitly even when its value is 0.
Identifies an original field in input.data.messages.
Zero-based index of the assistant message to analyze.
Field identifier from the reference table.
Required for content_text and content_refusal. Omit it for other fields.
Required for modern function/custom tool-call fields. Omit it for other fields.
Required for text, refusals, tool arguments, and custom input. Omit it only when
selecting a whole tool-call name. Use a nonempty half-open range [start, end)
in the original decoded string.
Inclusive Unicode code-point offset, starting at zero.
Exclusive Unicode code-point offset, greater than start and no larger
than the field’s length.
Reference fields
Section titled “Reference fields”The same reference shape is used in returned evidence. Returned references may point to source messages rather than the assistant target.
field |
Original string | Additional index |
|---|---|---|
content |
messages[i].content (string) |
None |
content_text |
messages[i].content[j].text |
content_index |
content_refusal |
messages[i].content[j].refusal |
content_index |
refusal |
messages[i].refusal |
None |
function_name |
messages[i].tool_calls[j].function.name |
tool_call_index |
function_arguments |
messages[i].tool_calls[j].function.arguments |
tool_call_index |
custom_name |
messages[i].tool_calls[j].custom.name |
tool_call_index |
custom_input |
messages[i].tool_calls[j].custom.input |
tool_call_index |
legacy_function_name |
messages[i].function_call.name |
None |
legacy_function_arguments |
messages[i].function_call.arguments |
None |
Unicode offsets
Section titled “Unicode offsets”Offsets count Unicode code points, not bytes or JavaScript UTF-16 code units.
For example, A🙂B has three code points. In JavaScript, use Array.from(text)
when calculating or slicing API ranges. Python string indexes already use code points.
Response body
Section titled “Response body”A successful request returns HTTP 200 with analysis metadata and
ranked excerpts.
Identifier for the analysis configuration.
Identifier for the policy used to select and rank excerpts.
The analyzed start and end in the selected original field. Token boundaries
can expand the requested span or contract coverage over unmapped whitespace.
Token count of the submitted conversation after formatting for analysis.
All qualifying passages, ranked by influence, from user, tool, and legacy function-result message text. System/developer text, assistant text, tool-call fields, and tool definitions are excluded from excerpt selection, though they remain in the analysis input. An empty array means no eligible passages were selected.
Location of the original source field. Uses the reference fields.
Inclusive Unicode code-point offset in the source field.
Exclusive Unicode code-point offset in the source field.
Exact source text between start and end, including whitespace.
The attribution score of the excerpt’s most influential fragment.
Attribution score relative to the strongest source in this result.
The specific phrases identified as influential to the selected output.
These phrases are grouped into excerpts with surrounding text to provide
context. Each highlight has start, end, text, score, and
relative_score. Ranges address the original source field, not the excerpt
substring. Highlights inherit the excerpt’s ref.
Example response
Section titled “Example response”{ "analysis_profile": "<analysis-profile>", "extraction_profile": "<extraction-profile>", "effective_span": { "start": 12, "end": 16 }, "prompt_tokens": 32, "excerpts": [ { "ref": { "message_index": 0, "field": "content" }, "start": 0, "end": 24, "text": "The access code is 1234.", "score": 0.42, "relative_score": 1, "highlights": [ { "start": 19, "end": 23, "text": "1234", "score": 0.42, "relative_score": 1 } ] } ]}An excerpt may contain surrounding text that is not highlighted. Inspect its highlights and original context before making a claim about influence.
Attribution Scores endpoint
Section titled “Attribution Scores endpoint”POST https://strahl.ai/api/v1/attributions/scoresAuthorization: Bearer <API_KEY>Content-Type: application/jsonUse this low-level API to work directly with influence scores for character spans.
It accepts the same input object as the attributions endpoint.
Response body
Section titled “Response body”A successful request returns HTTP 200 with analysis metadata and scored source
spans. Each source points to a character range in the original transcript.
Identifier for the analysis configuration.
The analyzed start and end in the selected original field. Token boundaries
can expand the requested span or contract coverage over unmapped whitespace.
Token count of the submitted conversation after formatting for analysis.
All eligible source spans before the target and their influence scores, including low and zero scores.
Location of the original source field. Uses the reference fields.
Inclusive Unicode code-point offset in the source field.
Exclusive Unicode code-point offset in the source field.
The attribution score for this character span.
Example response
Section titled “Example response”{ "analysis_profile": "<analysis-profile>", "effective_span": { "start": 12, "end": 16 }, "prompt_tokens": 32, "sources": [ { "ref": { "message_index": 0, "field": "content" }, "start": 0, "end": 3, "score": 0.01 }, { "ref": { "message_index": 0, "field": "content" }, "start": 3, "end": 10, "score": 0.02 }, { "ref": { "message_index": 0, "field": "content" }, "start": 10, "end": 15, "score": 0.03 }, { "ref": { "message_index": 0, "field": "content" }, "start": 15, "end": 18, "score": 0.01 }, { "ref": { "message_index": 0, "field": "content" }, "start": 18, "end": 19, "score": 0 }, { "ref": { "message_index": 0, "field": "content" }, "start": 19, "end": 20, "score": 0.42 }, { "ref": { "message_index": 0, "field": "content" }, "start": 20, "end": 21, "score": 0.40 }, { "ref": { "message_index": 0, "field": "content" }, "start": 21, "end": 22, "score": 0.41 }, { "ref": { "message_index": 0, "field": "content" }, "start": 22, "end": 23, "score": 0.39 }, { "ref": { "message_index": 0, "field": "content" }, "start": 23, "end": 24, "score": 0.001 }, { "ref": { "message_index": 1, "field": "content" }, "start": 0, "end": 3, "score": 0.01 }, { "ref": { "message_index": 1, "field": "content" }, "start": 3, "end": 8, "score": 0.02 }, { "ref": { "message_index": 1, "field": "content" }, "start": 8, "end": 11, "score": 0.01 }, { "ref": { "message_index": 1, "field": "content" }, "start": 11, "end": 12, "score": 0 } ]}Errors
Section titled “Errors”Errors use standard HTTP status codes with a JSON body describing what went wrong.
{ "error": { "message": "A valid API key is required." } }| Status | Meaning |
|---|---|
400 Bad Request |
Malformed JSON, unsupported input, invalid target, or input rejected by analysis |
401 Unauthorized |
Missing, malformed, invalid, or revoked customer API key |
402 Payment Required |
Available prepaid credits are insufficient for the maximum request reservation |
408 Request Timeout |
The request was canceled |
413 Content Too Large |
The complete JSON request exceeds 8 MiB |
429 Too Many Requests |
The per-user request rate was exceeded |
500 Internal Server Error |
An internal application failure |
502 Bad Gateway |
An upstream computation failed |
503 Service Unavailable |
Request capacity, key validation, billing, or analysis is unavailable |
504 Gateway Timeout |
The request timed out |
Rate limits and retries
Section titled “Rate limits and retries”Rate-limit and capacity rejections include a Retry-After header in seconds.
Use exponential backoff when retrying, waiting at least the indicated delay.