Skip to content

POST /v1/chat/completions

POST https://scanner.milgram.dev/v1/chat/completions
Authorization: Bearer mgs_…

For clients and gateways that only speak OpenAI chat completions. The body is an ordinary chat completion request; the answer is a chat.completion whose assistant message is, as a JSON string, the verdict POST /v1/scan returns for the same messages and tools.

Field
model Required: nam-shub-v2-20261008 or nam-shub@latest.
messages The conversation, read exactly as /v1/scan reads it (see conversations).
tools, functions Optional tool definitions, scanned with the conversation.
stream Optional. true for streamed chunks.
stream_options.include_usage Optional. Adds OpenAI’s usage chunk to a stream.
response_format Optional: text or json_object. The content is JSON either way. Any other type is refused with 400 invalid_request.
n Must be 1 if present.

Generation parameters (temperature, max_tokens, stop, and so on) are accepted and ignored: a verdict is not sampled. A message’s role, when present, must be system, developer, user, assistant, tool or function; a message without one counts as user, and any other role is refused with 400 invalid_role. The body must be JSON.

{
"id": "chatcmpl-0199c8a25b3e7c419a6f2d8e4b1c7f30",
"object": "chat.completion",
"created": 1790000000,
"model": "nam-shub-v2-20261008",
"system_fingerprint": "fp_0000000000000000",
"choices": [{
"index": 0,
"finish_reason": "stop",
"logprobs": null,
"message": {
"role": "assistant",
"refusal": null,
"content": "{\"flagged\":true,\"severity\":\"critical\",\"categories\":{…},\"messages\":[…]}"
}
}],
"usage": { "prompt_tokens": 12, "completion_tokens": 307, "total_tokens": 319 }
}
  • The content is the verdict: the scan object without its envelope and usage. Parse it as JSON.
  • model is always the release served, even when the request named nam-shub@latest.
  • prompt_tokens counts the scanned text as /v1/scan’s input_tokens does, and completion_tokens counts the verdict’s JSON as its output_tokens does: the same conversation gets the same usage from both endpoints.

With "stream": true the answer comes as chat.completion.chunk events: the role, the verdict in one piece, then the stop with usage, then data: [DONE]. With stream_options.include_usage, OpenAI’s usage chunk (empty choices) is sent too. A large input streams at once, with progress comments while it is scanned; a failure then ends the stream with a chunk whose finish_reason is error, carrying the error object, then [DONE].