{
"response": "Hello Juan, my name is Jakinen",
"user_events": [
{
"name": "take",
"item": "sword"
},
{
"name": "dance",
"item": null
}
]
}
"Unauthorized, no token provided"
"Unauthorized, invalid token provided. Try generating a new token."
"There is no world context defined."
"Error creating interaction"
Interactions
Obtain a response from an NPC character
Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character.
Response modes
Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events.
Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction:
stream.accepted – confirms language / session and that generation started.
Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively.
Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model).
stream.end – delivers the final transcript plus user_events, character_events, and usage totals.
You may cancel an ongoing generation by sending {"type":"interaction.cancel"}.
Voice live add-on (WebSocket only)
Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream.* text flow and emits supplemental voice.* events:
voice.ready, voice.session.updated — Azure Voice Live session lifecycle.
A JSON, XML, or URL-encoded payload containing the complete conversation history. Ensure messages are sent as an array of objects following the defined schema.
The Interaction schema defines the structure for a conversation between a player and an NPC. It includes metadata such as character ID, game ID, world ID, and an array of messages.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"NPC Builder","colors":{"primary":"#359BFA","light":"#359BFA","dark":"#0568c4"},"logo":{"light":"https://mintcdn.com/npcbuilder/0CmGufgM37ouZbOi/logo/light.svg?fit=max\u0026auto=format\u0026n=0CmGufgM37ouZbOi\u0026q=85\u0026s=21547db5a4d1774f17945bfd86336bc0","dark":"https://mintcdn.com/npcbuilder/0CmGufgM37ouZbOi/logo/dark.svg?fit=max\u0026auto=format\u0026n=0CmGufgM37ouZbOi\u0026q=85\u0026s=e633c1ee307d9a3a29fc2f98d2d9303b","href":"https://docs.npcbuilder.com"},"favicon":"https://mintcdn.com/npcbuilder/R4Y8o_1f-ZPlMdqS/favicon.svg?fit=max\u0026auto=format\u0026n=R4Y8o_1f-ZPlMdqS\u0026q=85\u0026s=98df48f15eaac008aba7d9697b8d62ea","navbar":{"links":[{"href":"mailto:support@npcbuilder.com","label":"Support"},{"icon":"calendar-check","href":"https://npcbuilder.com/plans","label":"Subscribe"}],"primary":{"type":"button","label":"App","href":"https://app.npcbuilder.com"}},"footer":{"socials":{"x":"https://x.com/npc_builder","github":"https://github.com/NPC-Builder","linkedin":"https://www.linkedin.com/company/npc-builder","youtube":"https://www.youtube.com/@NPCBuilderApp","instagram":"https://www.instagram.com/npc_builder"}},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Website","icon":"book-open-cover","href":"https://npcbuilder.com/"},{"anchor":"Community","icon":"discord","href":"https://discord.gg/9D6Xdj2MPU"}]},"languages":[{"language":"en","href":""},{"language":"es","href":"es"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"npcbuilder","hasAudioNarration":false,"actualSubdomain":"npcbuilder","customDomains":["docs.npcbuilder.com"],"gitSource":{"type":"github","owner":"npc-builder","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6a21e7608d1fcd719df0531d","collectionId":"440e3997-f4e1-4d2f-8504-a1fc02f1af1f","schemaVersion":"v2"},"entitlements":{},"buildId":"6a21e7608d1fcd719df0531d:success","clientVersion":"0.0.3965","searchFilterCounts":[{"language":"en","tag":"API reference","count":24},{"language":"es","tag":"Referencia de API","count":24},{"language":"en","tag":"Endpoints","count":23},{"language":"es","tag":"Endpoints","count":23},{"language":"en","tag":"Guides","count":6},{"language":"en","tag":"Getting started","count":4},{"language":"en","tag":"Characters","count":4},{"language":"en","tag":"Interactions","count":4},{"language":"en","tag":"Locations","count":4},{"language":"en","tag":"Regions","count":4},{"language":"en","tag":"Worlds","count":4},{"language":"es","tag":"Characters","count":4},{"language":"es","tag":"Interactions","count":4},{"language":"es","tag":"Locations","count":4},{"language":"es","tag":"Regions","count":4},{"language":"es","tag":"Worlds","count":4},{"language":"en","tag":"Sessions","count":3},{"language":"es","tag":"Guías","count":3},{"language":"es","tag":"Sessions","count":3},{"language":"es","tag":"Integraciones","count":2}]},"assistantConfig":{},"hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"#card img,#navbar img{width:180px;height:auto}#card img{width:80px}"}],"page":{"pagePath":"api-reference/interactions/obtain-a-response-from-an-npc-character","slug":"/api-reference/interactions/obtain-a-response-from-an-npc-character","pageMetadata":{"title":"Obtain a response from an NPC character","description":"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character.\n**Response modes**\n- **Batch HTTP (default):** Perform a regular `POST https://app.npcbuilder.com/api/interactions` request. The service buffers the model response and returns a single JSON payload that includes `response`, `user_events`, and `character_events`.\n- **Streaming WebSocket:** Open a WebSocket connection to `wss://api.app.npcbuilder.com/api/interactions`. Once the socket is accepted, send a JSON envelope in the following format to start the interaction:\n\n ```json\n {\n \"type\": \"interaction.start\",\n \"payload\": { ...interaction body... },\n \"meta\": {\n \"language\": \"en-US\",\n \"session_id\": \"optional-session\"\n }\n }\n ```\n\n The server answers with:\n\n * `stream.accepted` – confirms language / session and that generation started.\n * Multiple `stream.delta` events – each contains the next safe sentence so that you can render audio/voice progressively.\n * Optional `stream.safe_response` – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model).\n * `stream.end` – delivers the final transcript plus `user_events`, `character_events`, and usage totals. \n\n You may cancel an ongoing generation by sending `{\"type\":\"interaction.cancel\"}`.\n\n**Voice live add-on (WebSocket only)**\n- Connect to `wss://api.app.npcbuilder.com/api/interactions?voice=true` for full duplex voice, or use `voice=input` / `voice=output` for one-way voice. You can also provide `meta.voice` inside `interaction.start`. - When voice is enabled the service mirrors the normal `stream.*` text flow **and** emits supplemental `voice.*` events:\n - `voice.ready`, `voice.session.updated` — Azure Voice Live session lifecycle.\n - `voice.audio.delta`, `voice.audio.timestamp`, `voice.audio.done`, `voice.response.done` — assistant text-to-speech audio.\n - `voice.transcript.delta`, `voice.input.started/stopped`, `voice.usage` — microphone audio that was ingested through speech-to-text.\n- Client commands accepted during an active session:\n\n ```json\n { \"type\": \"voice.input.append\", \"data\": { \"audio\": \"\u003cbase64 pcm16 chunk>\" } }\n { \"type\": \"voice.input.commit\" }\n { \"type\": \"voice.input.clear\" }\n { \"type\": \"voice.session.update\", \"data\": { \"voice_name\": \"en-US-Ava:DragonHDLatestNeural\" } }\n { \"type\": \"voice.cancel\" }\n ```\n\nText streaming is never disabled—`stream.delta` and the final `stream.end` payload always include the transcript even if voice playback is on.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /interactions","href":"/api-reference/interactions/obtain-a-response-from-an-npc-character","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n p: \"p\",\n pre: \"pre\",\n span: \"span\",\n strong: \"strong\",\n ul: \"ul\",\n ..._provideComponents(),\n ...props.components\n }, {CodeBlock} = _components;\n if (!CodeBlock) _missingMdxReference(\"CodeBlock\", true);\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character.\\n\", _jsx(_components.strong, {\n children: \"Response modes\"\n })]\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [\"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"Batch HTTP (default):\"\n }), \" Perform a regular \", _jsx(_components.code, {\n children: \"POST https://app.npcbuilder.com/api/interactions\"\n }), \" request. The service buffers the model response and returns a single JSON payload that includes \", _jsx(_components.code, {\n children: \"response\"\n }), \", \", _jsx(_components.code, {\n children: \"user_events\"\n }), \", and \", _jsx(_components.code, {\n children: \"character_events\"\n }), \".\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.strong, {\n children: \"Streaming WebSocket:\"\n }), \" Open a WebSocket connection to \", _jsx(_components.code, {\n children: \"wss://api.app.npcbuilder.com/api/interactions\"\n }), \". Once the socket is accepted, send a JSON envelope in the following format to start the interaction:\"]\n }), \"\\n\", _jsx(CodeBlock, {\n numberOfLines: \"8\",\n language: \"json\",\n children: _jsx(_components.pre, {\n className: \"shiki shiki-themes github-light-default dark-plus\",\n style: {\n backgroundColor: \"#ffffff\",\n \"--shiki-dark-bg\": \"#0B0C0E\",\n color: \"#1f2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n language: \"json\",\n children: _jsxs(_components.code, {\n language: \"json\",\n numberOfLines: \"8\",\n children: [_jsx(_components.span, {\n className: \"line\",\n children: _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{\"\n })\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \" \\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"interaction.start\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \",\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \" \\\"payload\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": { \"\n }), _jsx(_components.span, {\n style: {\n color: \"#82071E\",\n \"--shiki-light-font-style\": \"italic\",\n \"--shiki-dark\": \"#F44747\",\n \"--shiki-dark-font-style\": \"inherit\"\n },\n children: \"...interaction\"\n }), _jsx(_components.span, {\n style: {\n color: \"#82071E\",\n \"--shiki-light-font-style\": \"italic\",\n \"--shiki-dark\": \"#F44747\",\n \"--shiki-dark-font-style\": \"inherit\"\n },\n children: \" body...\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" },\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \" \\\"meta\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": {\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \" \\\"language\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"en-US\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \",\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \" \\\"session_id\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"optional-session\\\"\"\n })]\n }), \"\\n\", _jsx(_components.span, {\n className: \"line\",\n children: _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" }\"\n })\n }), \"\\n\", _jsx(_components.span, {\n className: \"line\",\n children: _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"}\"\n })\n }), \"\\n\"]\n })\n })\n }), \"\\n\", _jsx(_components.p, {\n children: \"The server answers with:\"\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"stream.accepted\"\n }), \" – confirms language / session and that generation started.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Multiple \", _jsx(_components.code, {\n children: \"stream.delta\"\n }), \" events – each contains the next safe sentence so that you can render audio/voice progressively.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Optional \", _jsx(_components.code, {\n children: \"stream.safe_response\"\n }), \" – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model).\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"stream.end\"\n }), \" – delivers the final transcript plus \", _jsx(_components.code, {\n children: \"user_events\"\n }), \", \", _jsx(_components.code, {\n children: \"character_events\"\n }), \", and usage totals.\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"You may cancel an ongoing generation by sending \", _jsx(_components.code, {\n children: \"{\\\"type\\\":\\\"interaction.cancel\\\"}\"\n }), \".\"]\n }), \"\\n\"]\n }), \"\\n\"]\n }), \"\\n\", _jsx(_components.p, {\n children: _jsx(_components.strong, {\n children: \"Voice live add-on (WebSocket only)\"\n })\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [\"\\n\", _jsxs(_components.p, {\n children: [\"Connect to \", _jsx(_components.code, {\n children: \"wss://api.app.npcbuilder.com/api/interactions?voice=true\"\n }), \" for full duplex voice, or use \", _jsx(_components.code, {\n children: \"voice=input\"\n }), \" / \", _jsx(_components.code, {\n children: \"voice=output\"\n }), \" for one-way voice. You can also provide \", _jsx(_components.code, {\n children: \"meta.voice\"\n }), \" inside \", _jsx(_components.code, {\n children: \"interaction.start\"\n }), \". - When voice is enabled the service mirrors the normal \", _jsx(_components.code, {\n children: \"stream.*\"\n }), \" text flow \", _jsx(_components.strong, {\n children: \"and\"\n }), \" emits supplemental \", _jsx(_components.code, {\n children: \"voice.*\"\n }), \" events:\"]\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"voice.ready\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.session.updated\"\n }), \" — Azure Voice Live session lifecycle.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"voice.audio.delta\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.audio.timestamp\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.audio.done\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.response.done\"\n }), \" — assistant text-to-speech audio.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"voice.transcript.delta\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.input.started/stopped\"\n }), \", \", _jsx(_components.code, {\n children: \"voice.usage\"\n }), \" — microphone audio that was ingested through speech-to-text.\"]\n }), \"\\n\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"\\n\", _jsx(_components.p, {\n children: \"Client commands accepted during an active session:\"\n }), \"\\n\", _jsx(CodeBlock, {\n numberOfLines: \"5\",\n language: \"json\",\n children: _jsx(_components.pre, {\n className: \"shiki shiki-themes github-light-default dark-plus\",\n style: {\n backgroundColor: \"#ffffff\",\n \"--shiki-dark-bg\": \"#0B0C0E\",\n color: \"#1f2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n language: \"json\",\n children: _jsxs(_components.code, {\n language: \"json\",\n numberOfLines: \"5\",\n children: [_jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{ \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"voice.input.append\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \", \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"data\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": { \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"audio\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"\u003cbase64 pcm16 chunk>\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" } }\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{ \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"voice.input.commit\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" }\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{ \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"voice.input.clear\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" }\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{ \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"voice.session.update\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \", \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"data\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": { \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"voice_name\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"en-US-Ava:DragonHDLatestNeural\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" } }\"\n })]\n }), \"\\n\", _jsxs(_components.span, {\n className: \"line\",\n children: [_jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \"{ \"\n }), _jsx(_components.span, {\n style: {\n color: \"#116329\",\n \"--shiki-dark\": \"#9CDCFE\"\n },\n children: \"\\\"type\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \": \"\n }), _jsx(_components.span, {\n style: {\n color: \"#0A3069\",\n \"--shiki-dark\": \"#CE9178\"\n },\n children: \"\\\"voice.cancel\\\"\"\n }), _jsx(_components.span, {\n style: {\n color: \"#1F2328\",\n \"--shiki-dark\": \"#D4D4D4\"\n },\n children: \" }\"\n })]\n }), \"\\n\"]\n })\n })\n }), \"\\n\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Text streaming is never disabled—\", _jsx(_components.code, {\n children: \"stream.delta\"\n }), \" and the final \", _jsx(_components.code, {\n children: \"stream.end\"\n }), \" payload always include the transcript even if voice playback is on.\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\nfunction _missingMdxReference(id, component) {\n throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\");\n}\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Obtain a response from an NPC character","description":"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character.\n**Response modes**\n- **Batch HTTP (default):** Perform a regular `POST https://app.npcbuilder.com/api/interactions` request. The service buffers the model response and returns a single JSON payload that includes `response`, `user_events`, and `character_events`.\n- **Streaming WebSocket:** Open a WebSocket connection to `wss://api.app.npcbuilder.com/api/interactions`. Once the socket is accepted, send a JSON envelope in the following format to start the interaction:\n\n ```json\n {\n \"type\": \"interaction.start\",\n \"payload\": { ...interaction body... },\n \"meta\": {\n \"language\": \"en-US\",\n \"session_id\": \"optional-session\"\n }\n }\n ```\n\n The server answers with:\n\n * `stream.accepted` – confirms language / session and that generation started.\n * Multiple `stream.delta` events – each contains the next safe sentence so that you can render audio/voice progressively.\n * Optional `stream.safe_response` – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model).\n * `stream.end` – delivers the final transcript plus `user_events`, `character_events`, and usage totals. \n\n You may cancel an ongoing generation by sending `{\"type\":\"interaction.cancel\"}`.\n\n**Voice live add-on (WebSocket only)**\n- Connect to `wss://api.app.npcbuilder.com/api/interactions?voice=true` for full duplex voice, or use `voice=input` / `voice=output` for one-way voice. You can also provide `meta.voice` inside `interaction.start`. - When voice is enabled the service mirrors the normal `stream.*` text flow **and** emits supplemental `voice.*` events:\n - `voice.ready`, `voice.session.updated` — Azure Voice Live session lifecycle.\n - `voice.audio.delta`, `voice.audio.timestamp`, `voice.audio.done`, `voice.response.done` — assistant text-to-speech audio.\n - `voice.transcript.delta`, `voice.input.started/stopped`, `voice.usage` — microphone audio that was ingested through speech-to-text.\n- Client commands accepted during an active session:\n\n ```json\n { \"type\": \"voice.input.append\", \"data\": { \"audio\": \"\u003cbase64 pcm16 chunk>\" } }\n { \"type\": \"voice.input.commit\" }\n { \"type\": \"voice.input.clear\" }\n { \"type\": \"voice.session.update\", \"data\": { \"voice_name\": \"en-US-Ava:DragonHDLatestNeural\" } }\n { \"type\": \"voice.cancel\" }\n ```\n\nText streaming is never disabled—`stream.delta` and the final `stream.end` payload always include the transcript even if voice playback is on.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /interactions","href":"/api-reference/interactions/obtain-a-response-from-an-npc-character","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Interactions"],"summary":"Obtain a response from an NPC character","description":"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character.\n**Response modes**\n- **Batch HTTP (default):** Perform a regular `POST https://app.npcbuilder.com/api/interactions` request. The service buffers the model response and returns a single JSON payload that includes `response`, `user_events`, and `character_events`.\n- **Streaming WebSocket:** Open a WebSocket connection to `wss://api.app.npcbuilder.com/api/interactions`. Once the socket is accepted, send a JSON envelope in the following format to start the interaction:\n\n ```json\n {\n \"type\": \"interaction.start\",\n \"payload\": { ...interaction body... },\n \"meta\": {\n \"language\": \"en-US\",\n \"session_id\": \"optional-session\"\n }\n }\n ```\n\n The server answers with:\n\n * `stream.accepted` – confirms language / session and that generation started.\n * Multiple `stream.delta` events – each contains the next safe sentence so that you can render audio/voice progressively.\n * Optional `stream.safe_response` – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model).\n * `stream.end` – delivers the final transcript plus `user_events`, `character_events`, and usage totals. \n\n You may cancel an ongoing generation by sending `{\"type\":\"interaction.cancel\"}`.\n\n**Voice live add-on (WebSocket only)**\n- Connect to `wss://api.app.npcbuilder.com/api/interactions?voice=true` for full duplex voice, or use `voice=input` / `voice=output` for one-way voice. You can also provide `meta.voice` inside `interaction.start`. - When voice is enabled the service mirrors the normal `stream.*` text flow **and** emits supplemental `voice.*` events:\n - `voice.ready`, `voice.session.updated` — Azure Voice Live session lifecycle.\n - `voice.audio.delta`, `voice.audio.timestamp`, `voice.audio.done`, `voice.response.done` — assistant text-to-speech audio.\n - `voice.transcript.delta`, `voice.input.started/stopped`, `voice.usage` — microphone audio that was ingested through speech-to-text.\n- Client commands accepted during an active session:\n\n ```json\n { \"type\": \"voice.input.append\", \"data\": { \"audio\": \"\u003cbase64 pcm16 chunk>\" } }\n { \"type\": \"voice.input.commit\" }\n { \"type\": \"voice.input.clear\" }\n { \"type\": \"voice.session.update\", \"data\": { \"voice_name\": \"en-US-Ava:DragonHDLatestNeural\" } }\n { \"type\": \"voice.cancel\" }\n ```\n\nText streaming is never disabled—`stream.delta` and the final `stream.end` payload always include the transcript even if voice playback is on.\n","operationId":"addInteraction","servers":["81c6a888-5359-406d-99c0-0c75e676bed2","23c548c1-cc97-40a7-9110-e6401f59a01f"],"x-websocket":{"textStreamingUrl":"wss://api.app.npcbuilder.com/api/interactions","voiceStreamingUrl":"wss://api.app.npcbuilder.com/api/interactions?voice=true","voiceModes":["true","input","output"],"clientMessages":["interaction.start","interaction.cancel","voice.input.append","voice.input.commit","voice.input.clear","voice.session.update","voice.cancel"],"serverEvents":["stream.accepted","stream.delta","stream.safe_response","stream.end","stream.error","voice.ready","voice.session.updated","voice.audio.delta","voice.audio.timestamp","voice.audio.done","voice.response.done","voice.transcript.delta","voice.input.started","voice.input.stopped","voice.usage"]},"parameters":["4a50b2ca-85a2-41f5-a3d5-e4745529b6b8","05030c07-dc15-4294-9309-55d5b81d23ec","18278b88-5e6a-4429-a74d-8d3d14e5550e"],"requestBody":"8624b480-c35c-4937-be7d-2f118a0d2ab5","responses":{"200":"329a77b1-8467-4bec-99ba-0aa857c1dc3c","206":"64e252fe-3c6c-4d97-ad86-e718e16e7f64","401":"3d63d02f-4c84-47ce-ad09-8473845cbea1","403":"e55891ef-b05a-44e0-9762-e1c4394445ec","409":"6b6e6e16-1cde-4a68-a3ac-dc1282ea325c","500":"3753a0eb-168b-4b69-b7f0-a3862e47511e"},"security":["44c680ff-0863-4dfb-a74e-ffdb4da1ffc7"],"method":"post","type":"path","path":"/interactions","baseUrlOptions":["https://app.npcbuilder.com/api","wss://api.app.npcbuilder.com/api"],"title":"Obtain a response from an NPC character","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"4a50b2ca-85a2-41f5-a3d5-e4745529b6b8":{"name":"language","in":"query","description":"The language code for the interaction. Supported values include: - **en-US**: English (United States) - **es-ES**: Spanish (Spain)\n","required":true,"schema":{"type":"string","enum":["en-US","es-ES"],"example":"en-US","isRequired":true,"description":"The language code for the interaction. Supported values include: - **en-US**: English (United States) - **es-ES**: Spanish (Spain)\n","uniqueKey":"","typeLabel":"enum\u003cstring>"}},"05030c07-dc15-4294-9309-55d5b81d23ec":{"name":"session_id","in":"query","description":"(Optional) The unique identifier for the player's session.","required":false,"schema":{"type":"string","example":"60Z5aZjIuFlyYbjbZZKe","isRequired":false,"description":"(Optional) The unique identifier for the player's session.","uniqueKey":"","typeLabel":"string"}},"18278b88-5e6a-4429-a74d-8d3d14e5550e":{"name":"voice","in":"query","description":"Optional. Controls Azure Voice Live streaming when using WebSockets. Allowed values:\n* `false` (default): disable voice, text only. * `true`: enable full duplex (speech-to-text + text-to-speech). * `input`: only capture microphone input (speech-to-text). * `output`: only synthesize assistant audio (text-to-speech).\n","required":false,"schema":{"type":"string","enum":["false","true","input","output"],"default":"false","isRequired":false,"description":"Optional. Controls Azure Voice Live streaming when using WebSockets. Allowed values:\n* `false` (default): disable voice, text only. * `true`: enable full duplex (speech-to-text + text-to-speech). * `input`: only capture microphone input (speech-to-text). * `output`: only synthesize assistant audio (text-to-speech).\n","uniqueKey":"","typeLabel":"enum\u003cstring>"}}},"requestBody":{"description":"A JSON, XML, or URL-encoded payload containing the complete conversation history. Ensure messages are sent as an array of objects following the defined schema.\n","content":{"application/json":{"schema":{"type":"object","description":"The Interaction schema defines the structure for a conversation between a player and an NPC. It includes metadata such as character ID, game ID, world ID, and an array of messages.\n","properties":{"character_id":{"type":"string","description":"The unique identifier of the NPC character.","example":"a96c6161-59f5-40f7-955e-459cd11","uniqueKey":"character_id","typeLabel":"string"},"game_id":{"type":"string","description":"The unique identifier of the game.","example":"tx65BrETVN2vMrrUIrlV","uniqueKey":"game_id","typeLabel":"string"},"world_id":{"type":"string","description":"The unique identifier of the world.","example":"PtUYW5bLMZNnXPN8qAUJ","uniqueKey":"world_id","typeLabel":"string"},"conversation_id":{"type":"string","description":"(Optional) The unique identifier for the conversation history. If provided with empty messages, history will be loaded.","example":"conv_12345","uniqueKey":"conversation_id","typeLabel":"string"},"messages":{"type":"array","description":"An array of messages exchanged between the player and the NPC.","xml":{"name":"messages","wrapped":true},"items":{"type":"object","description":"A message object representing a single message in the conversation. The role indicates the sender ('user' for player messages, 'assistant' for NPC responses) and content holds the actual text.\n","properties":{"role":{"type":"string","description":"The role of the message sender. Use 'user' for messages from the player and 'assistant' for NPC responses.\n","enum":["user","assistant"],"example":"user","uniqueKey":"messages.items.[INDEX].role","typeLabel":"enum\u003cstring>"},"content":{"type":"string","description":"The text content of the message.","example":"Hello Jakinen, my name is Juan, I'll take my sword and dance!","uniqueKey":"messages.items.[INDEX].content","typeLabel":"string"}},"xml":{"name":"messages_user"},"uniqueKey":"messages.items.[INDEX]","typeLabel":"object"},"uniqueKey":"messages","typeLabel":"object[]"},"user_context":{"type":"object","description":"An object containing player-specific information for character context.","properties":{"name":{"type":"string","description":"The name of the player.","example":"Juan","uniqueKey":"user_context.name","typeLabel":"string"},"age":{"type":"string","description":"The age of the player.","example":"Adult","uniqueKey":"user_context.age","typeLabel":"string"},"gender":{"type":"string","description":"The gender of the player.","example":"Male","uniqueKey":"user_context.gender","typeLabel":"string"},"race":{"type":"string","description":"The race of the player.","example":"Human","uniqueKey":"user_context.race","typeLabel":"string"},"class":{"type":"string","description":"The class of the player.","example":"Warrior","uniqueKey":"user_context.class","typeLabel":"string"},"level":{"type":"integer","description":"The level of the player.","example":5,"uniqueKey":"user_context.level","typeLabel":"integer"},"status":{"type":"string","description":"The status of the player.","example":"Healthy","uniqueKey":"user_context.status","typeLabel":"string"},"description":{"type":"string","description":"A brief description of the player used for characterizing it or its status.","example":"Smelly with a big sword and a wound in the chest","uniqueKey":"user_context.description","typeLabel":"string"}},"uniqueKey":"user_context","typeLabel":"object"}},"xml":{"name":"interaction"},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"character_id":"a96c6161-59f5-40f7-955e-459cd11","game_id":"tx65BrETVN2vMrrUIrlV","world_id":"PtUYW5bLMZNnXPN8qAUJ","conversation_id":"conv_12345","messages":[{"role":"user","content":"Hello Jakinen, my name is Juan, I'll take my sword and dance!"}],"user_context":{"name":"Juan","age":"Adult","gender":"Male","race":"Human","class":"Warrior","level":5,"status":"Healthy","description":"Smelly with a big sword and a wound in the chest"}}}},"exampleType":"generated"},"application/xml":{"schema":{"type":"object","description":"The Interaction schema defines the structure for a conversation between a player and an NPC. It includes metadata such as character ID, game ID, world ID, and an array of messages.\n","properties":{"character_id":{"type":"string","description":"The unique identifier of the NPC character.","example":"a96c6161-59f5-40f7-955e-459cd11","uniqueKey":"character_id","typeLabel":"string"},"game_id":{"type":"string","description":"The unique identifier of the game.","example":"tx65BrETVN2vMrrUIrlV","uniqueKey":"game_id","typeLabel":"string"},"world_id":{"type":"string","description":"The unique identifier of the world.","example":"PtUYW5bLMZNnXPN8qAUJ","uniqueKey":"world_id","typeLabel":"string"},"conversation_id":{"type":"string","description":"(Optional) The unique identifier for the conversation history. If provided with empty messages, history will be loaded.","example":"conv_12345","uniqueKey":"conversation_id","typeLabel":"string"},"messages":{"type":"array","description":"An array of messages exchanged between the player and the NPC.","xml":{"name":"messages","wrapped":true},"items":{"type":"object","description":"A message object representing a single message in the conversation. The role indicates the sender ('user' for player messages, 'assistant' for NPC responses) and content holds the actual text.\n","properties":{"role":{"type":"string","description":"The role of the message sender. Use 'user' for messages from the player and 'assistant' for NPC responses.\n","enum":["user","assistant"],"example":"user","uniqueKey":"messages.items.[INDEX].role","typeLabel":"enum\u003cstring>"},"content":{"type":"string","description":"The text content of the message.","example":"Hello Jakinen, my name is Juan, I'll take my sword and dance!","uniqueKey":"messages.items.[INDEX].content","typeLabel":"string"}},"xml":{"name":"messages_user"},"uniqueKey":"messages.items.[INDEX]","typeLabel":"object"},"uniqueKey":"messages","typeLabel":"object[]"},"user_context":{"type":"object","description":"An object containing player-specific information for character context.","properties":{"name":{"type":"string","description":"The name of the player.","example":"Juan","uniqueKey":"user_context.name","typeLabel":"string"},"age":{"type":"string","description":"The age of the player.","example":"Adult","uniqueKey":"user_context.age","typeLabel":"string"},"gender":{"type":"string","description":"The gender of the player.","example":"Male","uniqueKey":"user_context.gender","typeLabel":"string"},"race":{"type":"string","description":"The race of the player.","example":"Human","uniqueKey":"user_context.race","typeLabel":"string"},"class":{"type":"string","description":"The class of the player.","example":"Warrior","uniqueKey":"user_context.class","typeLabel":"string"},"level":{"type":"integer","description":"The level of the player.","example":5,"uniqueKey":"user_context.level","typeLabel":"integer"},"status":{"type":"string","description":"The status of the player.","example":"Healthy","uniqueKey":"user_context.status","typeLabel":"string"},"description":{"type":"string","description":"A brief description of the player used for characterizing it or its status.","example":"Smelly with a big sword and a wound in the chest","uniqueKey":"user_context.description","typeLabel":"string"}},"uniqueKey":"user_context","typeLabel":"object"}},"xml":{"name":"interaction"},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"character_id":"a96c6161-59f5-40f7-955e-459cd11","game_id":"tx65BrETVN2vMrrUIrlV","world_id":"PtUYW5bLMZNnXPN8qAUJ","conversation_id":"conv_12345","messages":[{"role":"user","content":"Hello Jakinen, my name is Juan, I'll take my sword and dance!"}],"user_context":{"name":"Juan","age":"Adult","gender":"Male","race":"Human","class":"Warrior","level":5,"status":"Healthy","description":"Smelly with a big sword and a wound in the chest"}}}},"exampleType":"generated"},"application/x-www-form-urlencoded":{"schema":{"type":"object","description":"The Interaction schema defines the structure for a conversation between a player and an NPC. It includes metadata such as character ID, game ID, world ID, and an array of messages.\n","properties":{"character_id":{"type":"string","description":"The unique identifier of the NPC character.","example":"a96c6161-59f5-40f7-955e-459cd11","uniqueKey":"character_id","typeLabel":"string"},"game_id":{"type":"string","description":"The unique identifier of the game.","example":"tx65BrETVN2vMrrUIrlV","uniqueKey":"game_id","typeLabel":"string"},"world_id":{"type":"string","description":"The unique identifier of the world.","example":"PtUYW5bLMZNnXPN8qAUJ","uniqueKey":"world_id","typeLabel":"string"},"conversation_id":{"type":"string","description":"(Optional) The unique identifier for the conversation history. If provided with empty messages, history will be loaded.","example":"conv_12345","uniqueKey":"conversation_id","typeLabel":"string"},"messages":{"type":"array","description":"An array of messages exchanged between the player and the NPC.","xml":{"name":"messages","wrapped":true},"items":{"type":"object","description":"A message object representing a single message in the conversation. The role indicates the sender ('user' for player messages, 'assistant' for NPC responses) and content holds the actual text.\n","properties":{"role":{"type":"string","description":"The role of the message sender. Use 'user' for messages from the player and 'assistant' for NPC responses.\n","enum":["user","assistant"],"example":"user","uniqueKey":"messages.items.[INDEX].role","typeLabel":"enum\u003cstring>"},"content":{"type":"string","description":"The text content of the message.","example":"Hello Jakinen, my name is Juan, I'll take my sword and dance!","uniqueKey":"messages.items.[INDEX].content","typeLabel":"string"}},"xml":{"name":"messages_user"},"uniqueKey":"messages.items.[INDEX]","typeLabel":"object"},"uniqueKey":"messages","typeLabel":"object[]"},"user_context":{"type":"object","description":"An object containing player-specific information for character context.","properties":{"name":{"type":"string","description":"The name of the player.","example":"Juan","uniqueKey":"user_context.name","typeLabel":"string"},"age":{"type":"string","description":"The age of the player.","example":"Adult","uniqueKey":"user_context.age","typeLabel":"string"},"gender":{"type":"string","description":"The gender of the player.","example":"Male","uniqueKey":"user_context.gender","typeLabel":"string"},"race":{"type":"string","description":"The race of the player.","example":"Human","uniqueKey":"user_context.race","typeLabel":"string"},"class":{"type":"string","description":"The class of the player.","example":"Warrior","uniqueKey":"user_context.class","typeLabel":"string"},"level":{"type":"integer","description":"The level of the player.","example":5,"uniqueKey":"user_context.level","typeLabel":"integer"},"status":{"type":"string","description":"The status of the player.","example":"Healthy","uniqueKey":"user_context.status","typeLabel":"string"},"description":{"type":"string","description":"A brief description of the player used for characterizing it or its status.","example":"Smelly with a big sword and a wound in the chest","uniqueKey":"user_context.description","typeLabel":"string"}},"uniqueKey":"user_context","typeLabel":"object"}},"xml":{"name":"interaction"},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"character_id":"a96c6161-59f5-40f7-955e-459cd11","game_id":"tx65BrETVN2vMrrUIrlV","world_id":"PtUYW5bLMZNnXPN8qAUJ","conversation_id":"conv_12345","messages":[{"role":"user","content":"Hello Jakinen, my name is Juan, I'll take my sword and dance!"}],"user_context":{"name":"Juan","age":"Adult","gender":"Male","race":"Human","class":"Warrior","level":5,"status":"Healthy","description":"Smelly with a big sword and a wound in the chest"}}}},"exampleType":"generated"}},"required":true,"exampleType":"generated"},"responses":{"329a77b1-8467-4bec-99ba-0aa857c1dc3c":{"description":"Successful operation. Returns the character's response along with any triggered user events.\n","content":{"application/json":{"schema":{"type":"object","description":"The ApiResponse schema represents the successful response from the API, including the NPC's response and any user-triggered events.\n","properties":{"response":{"type":"string","description":"The NPC's generated response.","example":"Hello Juan, my name is Jakinen","uniqueKey":"response","typeLabel":"string"},"user_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"user_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"user_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"user_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"user_events","typeLabel":"object[]"},"character_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"character_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"character_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"character_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"character_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"character_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"character_events","typeLabel":"object[]"}},"example":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}],"character_events":[{"name":"give","item":"shield"},{"name":"attack","item":null}]},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}],"character_events":[{"name":"give","item":"shield"},{"name":"attack","item":null}]}}},"exampleType":"generated"},"application/xml":{"schema":{"type":"object","description":"The ApiResponse schema represents the successful response from the API, including the NPC's response and any user-triggered events.\n","properties":{"response":{"type":"string","description":"The NPC's generated response.","example":"Hello Juan, my name is Jakinen","uniqueKey":"response","typeLabel":"string"},"user_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"user_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"user_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"user_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"user_events","typeLabel":"object[]"},"character_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"character_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"character_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event, if any.","example":"sword","uniqueKey":"character_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"character_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"character_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"character_events","typeLabel":"object[]"}},"example":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}],"character_events":[{"name":"give","item":"shield"},{"name":"attack","item":null}]},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}],"character_events":[{"name":"give","item":"shield"},{"name":"attack","item":null}]}}},"exampleType":"generated"}},"exampleType":"generated"},"64e252fe-3c6c-4d97-ad86-e718e16e7f64":{"description":"Partial content due to maximum length reached. The response may be truncated.\n","content":{"application/json":{"schema":{"type":"object","description":"The MaxLength schema is used when the response has been truncated due to reaching the maximum allowed length.\n","properties":{"response":{"type":"string","description":"The truncated response from the NPC.","example":"Hello Juan, my name is Jakinen","uniqueKey":"response","typeLabel":"string"},"user_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"user_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"user_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"user_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"user_events","typeLabel":"object[]"}},"example":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}]},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}]}}},"exampleType":"generated"},"application/xml":{"schema":{"type":"object","description":"The MaxLength schema is used when the response has been truncated due to reaching the maximum allowed length.\n","properties":{"response":{"type":"string","description":"The truncated response from the NPC.","example":"Hello Juan, my name is Jakinen","uniqueKey":"response","typeLabel":"string"},"user_events":{"type":"array","description":"A list of events triggered by the user's input.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the event.","example":"take","uniqueKey":"user_events.items.[INDEX].name","typeLabel":"string"},"item":{"oneOf":[{"type":"string","description":"The item associated with the event.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.0","typeLabel":"string"},{"type":"null","description":"The item associated with the event.","example":"sword","uniqueKey":"user_events.items.[INDEX].item.oneOf.1","typeLabel":"null"}],"uniqueKey":"user_events.items.[INDEX].item","typeLabel":"string | null"}},"uniqueKey":"user_events.items.[INDEX]","typeLabel":"object"},"uniqueKey":"user_events","typeLabel":"object[]"}},"example":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}]},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"response":"Hello Juan, my name is Jakinen","user_events":[{"name":"take","item":"sword"},{"name":"dance","item":null}]}}},"exampleType":"generated"}},"exampleType":"generated"},"3d63d02f-4c84-47ce-ad09-8473845cbea1":{"description":"Unauthorized – No valid token was provided.","content":{"application/json":{"example":"Unauthorized, no token provided","examples":{"Example":{"title":"Example","value":"Unauthorized, no token provided"}},"exampleType":"examples"}},"exampleType":"examples"},"e55891ef-b05a-44e0-9762-e1c4394445ec":{"description":"Forbidden – Invalid token provided. Try generating a new token.","content":{"application/json":{"example":"Unauthorized, invalid token provided. Try generating a new token.","examples":{"Example":{"title":"Example","value":"Unauthorized, invalid token provided. Try generating a new token."}},"exampleType":"examples"}},"exampleType":"examples"},"6b6e6e16-1cde-4a68-a3ac-dc1282ea325c":{"description":"Conflict – Operation not allowed due to usage limits, non-existent objects, or unimplemented features.\n","content":{"application/json":{"schema":{"oneOf":[{"type":"string","description":"Error indicating that no world context has been defined.\n","example":"There is no world context defined.","uniqueKey":"oneOf.0","typeLabel":"string"},{"type":"string","description":"Error indicating that the usage limit has been exceeded.\n","example":"Usage limit exceeded. Please check your subscription or interactions limit.","uniqueKey":"oneOf.1","typeLabel":"string"},{"type":"string","description":"Error indicating that the requested operation is not implemented.\n","example":"Not implemented yet.","uniqueKey":"oneOf.2","typeLabel":"string"}],"uniqueKey":"","typeLabel":"string"},"examples":{"Example":{"title":"Example","value":"There is no world context defined."}},"exampleType":"generated"}},"exampleType":"generated"},"3753a0eb-168b-4b69-b7f0-a3862e47511e":{"description":"Internal Server Error – An error occurred while processing the interaction.\n","content":{"application/json":{"example":"Error creating interaction","examples":{"Example":{"title":"Example","value":"Error creating interaction"}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"44c680ff-0863-4dfb-a74e-ffdb4da1ffc7":{"npcbuilder_auth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","scopes":[]}}},"servers":{"81c6a888-5359-406d-99c0-0c75e676bed2":{"url":"https://app.npcbuilder.com/api","description":"Production HTTP API for batch interactions"},"23c548c1-cc97-40a7-9110-e6401f59a01f":{"url":"wss://api.app.npcbuilder.com/api","description":"Production WebSocket API for text streaming and voice interactions"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"JWT","scopes":[]},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Bearer authentication header of the form `Bearer \u003ctoken>`, where `\u003ctoken>` is your auth token.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"npcbuilder_auth","name":"Authorization"}],"title":"npcbuilder_auth"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"npcbuilder","siteName":"NPC Builder","title":"Obtain a response from an NPC character - NPC Builder","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"en":{"href":"/api-reference/interactions/obtain-a-response-from-an-npc-character","matchLevel":0},"es":{"href":"/es","matchLevel":4}}},"lastModified":"2026-05-23T17:44:12.298Z","originalFileLocation":"api-reference/interactions/obtain-a-response-from-an-npc-character.mdx","locale":"en"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character. Response modes - Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events. - Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction: json { \u0026quot;type\u0026quot;: \u0026quot;interaction.start\u0026quot;, \u0026quot;payload\u0026quot;: { ...interaction body... }, \u0026quot;meta\u0026quot;: { \u0026quot;language\u0026quot;: \u0026quot;en-US\u0026quot;, \u0026quot;session_id\u0026quot;: \u0026quot;optional-session\u0026quot; } } The server answers with: stream.accepted – confirms language / session and that generation started. Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively. Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model). stream.end – delivers the final transcript plus user_events, character_events, and usage totals. You may cancel an ongoing generation by sending {\u0026quot;type\u0026quot;:\u0026quot;interaction.cancel\u0026quot;}. Voice live add-on (WebSocket only) - Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream. text flow and emits supplemental voice. events: - voice.ready, voice.session.updated — Azure Voice Live session lifecycle. - voice.audio.delta, voice.audio.timestamp, voice.audio.done, voice.response.done — assistant text-to-speech audio. - voice.transcript.delta, voice.input.started/stopped, voice.usage — microphone audio that was ingested through speech-to-text. - Client commands accepted during an active session: json { \u0026quot;type\u0026quot;: \u0026quot;voice.input.append\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;audio\u0026quot;: \u0026quot;\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.commit\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.clear\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.session.update\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;voice_name\u0026quot;: \u0026quot;en-US-Ava:DragonHDLatestNeural\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.cancel\u0026quot; } Text streaming is never disabled—stream.delta and the final stream.end payload always include the transcript even if voice playback is on.\">\u003cmeta data-mint-head name=\"application-name\" content=\"NPC Builder\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Obtain a response from an NPC character - NPC Builder\">\u003cmeta data-mint-head property=\"og:description\" content=\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character. Response modes - Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events. - Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction: json { \u0026quot;type\u0026quot;: \u0026quot;interaction.start\u0026quot;, \u0026quot;payload\u0026quot;: { ...interaction body... }, \u0026quot;meta\u0026quot;: { \u0026quot;language\u0026quot;: \u0026quot;en-US\u0026quot;, \u0026quot;session_id\u0026quot;: \u0026quot;optional-session\u0026quot; } } The server answers with: stream.accepted – confirms language / session and that generation started. Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively. Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model). stream.end – delivers the final transcript plus user_events, character_events, and usage totals. You may cancel an ongoing generation by sending {\u0026quot;type\u0026quot;:\u0026quot;interaction.cancel\u0026quot;}. Voice live add-on (WebSocket only) - Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream. text flow and emits supplemental voice. events: - voice.ready, voice.session.updated — Azure Voice Live session lifecycle. - voice.audio.delta, voice.audio.timestamp, voice.audio.done, voice.response.done — assistant text-to-speech audio. - voice.transcript.delta, voice.input.started/stopped, voice.usage — microphone audio that was ingested through speech-to-text. - Client commands accepted during an active session: json { \u0026quot;type\u0026quot;: \u0026quot;voice.input.append\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;audio\u0026quot;: \u0026quot;\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.commit\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.clear\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.session.update\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;voice_name\u0026quot;: \u0026quot;en-US-Ava:DragonHDLatestNeural\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.cancel\u0026quot; } Text streaming is never disabled—stream.delta and the final stream.end payload always include the transcript even if voice playback is on.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"NPC Builder\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://npcbuilder.mintlify.app/_mintlify/api/og/v2?division=Interactions\u0026amp;title=Obtain+a+response+from+an+NPC+character\u0026amp;description=Send+an+array+of+interaction+messages+between+the+player+and+the+NPC+character.+The+API+processes+the+conversation+history+and+returns+a+new+response+generated+\u0026amp;theme=f88d1efe1e5661d6a3055fa0\u0026amp;signature=09b75425a4a8c7620e90a43036a1984dfbe5efb1cea6dc666f08732f82a4db59\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Obtain a response from an NPC character - NPC Builder\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character. Response modes - Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events. - Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction: json { \u0026quot;type\u0026quot;: \u0026quot;interaction.start\u0026quot;, \u0026quot;payload\u0026quot;: { ...interaction body... }, \u0026quot;meta\u0026quot;: { \u0026quot;language\u0026quot;: \u0026quot;en-US\u0026quot;, \u0026quot;session_id\u0026quot;: \u0026quot;optional-session\u0026quot; } } The server answers with: stream.accepted – confirms language / session and that generation started. Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively. Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model). stream.end – delivers the final transcript plus user_events, character_events, and usage totals. You may cancel an ongoing generation by sending {\u0026quot;type\u0026quot;:\u0026quot;interaction.cancel\u0026quot;}. Voice live add-on (WebSocket only) - Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream. text flow and emits supplemental voice. events: - voice.ready, voice.session.updated — Azure Voice Live session lifecycle. - voice.audio.delta, voice.audio.timestamp, voice.audio.done, voice.response.done — assistant text-to-speech audio. - voice.transcript.delta, voice.input.started/stopped, voice.usage — microphone audio that was ingested through speech-to-text. - Client commands accepted during an active session: json { \u0026quot;type\u0026quot;: \u0026quot;voice.input.append\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;audio\u0026quot;: \u0026quot;\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.commit\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.input.clear\u0026quot; } { \u0026quot;type\u0026quot;: \u0026quot;voice.session.update\u0026quot;, \u0026quot;data\u0026quot;: { \u0026quot;voice_name\u0026quot;: \u0026quot;en-US-Ava:DragonHDLatestNeural\u0026quot; } } { \u0026quot;type\u0026quot;: \u0026quot;voice.cancel\u0026quot; } Text streaming is never disabled—stream.delta and the final stream.end payload always include the transcript even if voice playback is on.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://npcbuilder.mintlify.app/_mintlify/api/og/v2?division=Interactions\u0026amp;title=Obtain+a+response+from+an+NPC+character\u0026amp;description=Send+an+array+of+interaction+messages+between+the+player+and+the+NPC+character.+The+API+processes+the+conversation+history+and+returns+a+new+response+generated+\u0026amp;theme=f88d1efe1e5661d6a3055fa0\u0026amp;signature=09b75425a4a8c7620e90a43036a1984dfbe5efb1cea6dc666f08732f82a4db59\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/npcbuilder/C1Zsc-PmxoJsczfU/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"NPC Builder\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#359BFA\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/interactions/obtain-a-response-from-an-npc-character.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.npcbuilder.com/#organization\",\"name\":\"NPC Builder\",\"url\":\"https://docs.npcbuilder.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/npcbuilder/0CmGufgM37ouZbOi/logo/light.svg?fit=max\u0026auto=format\u0026n=0CmGufgM37ouZbOi\u0026q=85\u0026s=21547db5a4d1774f17945bfd86336bc0\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.npcbuilder.com#website\",\"name\":\"NPC Builder\",\"url\":\"https://docs.npcbuilder.com\",\"publisher\":{\"@id\":\"https://docs.npcbuilder.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character#webpage\",\"url\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character\",\"name\":\"Obtain a response from an NPC character\",\"description\":\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character. Response modes - Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events. - Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction: json { \\\"type\\\": \\\"interaction.start\\\", \\\"payload\\\": { ...interaction body... }, \\\"meta\\\": { \\\"language\\\": \\\"en-US\\\", \\\"session_id\\\": \\\"optional-session\\\" } } The server answers with: stream.accepted – confirms language / session and that generation started. Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively. Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model). stream.end – delivers the final transcript plus user_events, character_events, and usage totals. You may cancel an ongoing generation by sending {\\\"type\\\":\\\"interaction.cancel\\\"}. Voice live add-on (WebSocket only) - Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream. text flow and emits supplemental voice. events: - voice.ready, voice.session.updated — Azure Voice Live session lifecycle. - voice.audio.delta, voice.audio.timestamp, voice.audio.done, voice.response.done — assistant text-to-speech audio. - voice.transcript.delta, voice.input.started/stopped, voice.usage — microphone audio that was ingested through speech-to-text. - Client commands accepted during an active session: json { \\\"type\\\": \\\"voice.input.append\\\", \\\"data\\\": { \\\"audio\\\": \\\"\\\" } } { \\\"type\\\": \\\"voice.input.commit\\\" } { \\\"type\\\": \\\"voice.input.clear\\\" } { \\\"type\\\": \\\"voice.session.update\\\", \\\"data\\\": { \\\"voice_name\\\": \\\"en-US-Ava:DragonHDLatestNeural\\\" } } { \\\"type\\\": \\\"voice.cancel\\\" } Text streaming is never disabled—stream.delta and the final stream.end payload always include the transcript even if voice playback is on.\",\"dateModified\":\"2026-05-23T17:44:12.298Z\",\"isPartOf\":{\"@id\":\"https://docs.npcbuilder.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"NPC Builder\",\"item\":\"https://docs.npcbuilder.com\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Obtain a response from an NPC character\",\"item\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character#apireference\",\"headline\":\"Obtain a response from an NPC character\",\"name\":\"Obtain a response from an NPC character\",\"description\":\"Send an array of interaction messages between the player and the NPC character. The API processes the conversation history and returns a new response generated by the character. Response modes - Batch HTTP (default): Perform a regular POST https://app.npcbuilder.com/api/interactions request. The service buffers the model response and returns a single JSON payload that includes response, user_events, and character_events. - Streaming WebSocket: Open a WebSocket connection to wss://api.app.npcbuilder.com/api/interactions. Once the socket is accepted, send a JSON envelope in the following format to start the interaction: json { \\\"type\\\": \\\"interaction.start\\\", \\\"payload\\\": { ...interaction body... }, \\\"meta\\\": { \\\"language\\\": \\\"en-US\\\", \\\"session_id\\\": \\\"optional-session\\\" } } The server answers with: stream.accepted – confirms language / session and that generation started. Multiple stream.delta events – each contains the next safe sentence so that you can render audio/voice progressively. Optional stream.safe_response – emitted if a banned phrase is detected mid-stream (it also aborts the upstream model). stream.end – delivers the final transcript plus user_events, character_events, and usage totals. You may cancel an ongoing generation by sending {\\\"type\\\":\\\"interaction.cancel\\\"}. Voice live add-on (WebSocket only) - Connect to wss://api.app.npcbuilder.com/api/interactions?voice=true for full duplex voice, or use voice=input / voice=output for one-way voice. You can also provide meta.voice inside interaction.start. - When voice is enabled the service mirrors the normal stream. text flow and emits supplemental voice. events: - voice.ready, voice.session.updated — Azure Voice Live session lifecycle. - voice.audio.delta, voice.audio.timestamp, voice.audio.done, voice.response.done — assistant text-to-speech audio. - voice.transcript.delta, voice.input.started/stopped, voice.usage — microphone audio that was ingested through speech-to-text. - Client commands accepted during an active session: json { \\\"type\\\": \\\"voice.input.append\\\", \\\"data\\\": { \\\"audio\\\": \\\"\\\" } } { \\\"type\\\": \\\"voice.input.commit\\\" } { \\\"type\\\": \\\"voice.input.clear\\\" } { \\\"type\\\": \\\"voice.session.update\\\", \\\"data\\\": { \\\"voice_name\\\": \\\"en-US-Ava:DragonHDLatestNeural\\\" } } { \\\"type\\\": \\\"voice.cancel\\\" } Text streaming is never disabled—stream.delta and the final stream.end payload always include the transcript even if voice playback is on.\",\"url\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character\",\"mainEntityOfPage\":{\"@id\":\"https://docs.npcbuilder.com/api-reference/interactions/obtain-a-response-from-an-npc-character#webpage\"},\"dateModified\":\"2026-05-23T17:44:12.298Z\",\"publisher\":{\"@id\":\"https://docs.npcbuilder.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.npcbuilder.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"NPC Builder\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"NPC Builder","nav":{"global":{"anchors":[{"anchor":"Website","icon":"book-open-cover","href":"https://npcbuilder.com/"},{"anchor":"Community","icon":"discord","href":"https://discord.gg/9D6Xdj2MPU"}]},"languages":[{"language":"en","tabs":[{"tab":"Guides","icon":"book","pages":[{"title":"Guides","href":""}]},{"tab":"API reference","icon":"code","pages":[{"group":"API documentation","pages":[{"title":"Introduction","href":"/api-reference/introduction"},{"title":"Uids","href":"/api-reference/uids"},{"title":"Authentication","href":"/api-reference/authentication"}]},{"group":"Endpoints","pages":[{"group":"Interactions","pages":[{"title":"Obtain a response from an NPC character","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /interactions","href":"/api-reference/interactions/obtain-a-response-from-an-npc-character"},{"title":"List conversations","description":"Retrieve a list of conversations for a specific game. You can filter by session, character, or player.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /conversations","href":"/api-reference/interactions/list-conversations"},{"title":"Create a new conversation","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /conversations","href":"/api-reference/interactions/create-a-new-conversation"},{"title":"Get conversation history","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /conversations/{id}","href":"/api-reference/interactions/get-conversation-history"}]},{"group":"Characters","pages":[{"title":"Create a new character","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /context/characters/{game_id}/{world_id}","href":"/api-reference/characters/create-a-new-character"},{"title":"Get character details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /context/characters/{game_id}/{world_id}/{character_id}","href":"/api-reference/characters/get-character-details"},{"title":"Delete a character","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /context/characters/{game_id}/{world_id}/{character_id}","href":"/api-reference/characters/delete-a-character"},{"title":"Update character details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /context/characters/{game_id}/{world_id}/{character_id}","href":"/api-reference/characters/update-character-details"}]},{"group":"Worlds","pages":[{"title":"Create a new world","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /context/world/{game_id}","href":"/api-reference/worlds/create-a-new-world"},{"title":"Get world details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /context/world/{game_id}/{world_id}","href":"/api-reference/worlds/get-world-details"},{"title":"Delete a world","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /context/world/{game_id}/{world_id}","href":"/api-reference/worlds/delete-a-world"},{"title":"Update world details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /context/world/{game_id}/{world_id}","href":"/api-reference/worlds/update-world-details"}]},{"group":"Regions","pages":[{"title":"Create a new region","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /context/region/{game_id}/{world_id}","href":"/api-reference/regions/create-a-new-region"},{"title":"Get region details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /context/region/{game_id}/{world_id}/{region_id}","href":"/api-reference/regions/get-region-details"},{"title":"Delete a region","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /context/region/{game_id}/{world_id}/{region_id}","href":"/api-reference/regions/delete-a-region"},{"title":"Update region details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /context/region/{game_id}/{world_id}/{region_id}","href":"/api-reference/regions/update-region-details"}]},{"group":"Locations","pages":[{"title":"Create a new location","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /context/location/{game_id}/{world_id}/{region_id}","href":"/api-reference/locations/create-a-new-location"},{"title":"Get location details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /context/location/{game_id}/{world_id}/{location_id}","href":"/api-reference/locations/get-location-details"},{"title":"Delete a location","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /context/location/{game_id}/{world_id}/{location_id}","href":"/api-reference/locations/delete-a-location"},{"title":"Update location details","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /context/location/{game_id}/{world_id}/{location_id}","href":"/api-reference/locations/update-location-details"}]},{"group":"Sessions","pages":[{"title":"Retrieve session information","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /sessionmanager","href":"/api-reference/sessions/retrieve-session-information"},{"title":"Create a new session","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /sessionmanager","href":"/api-reference/sessions/create-a-new-session"},{"title":"Delete a session","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /sessionmanager","href":"/api-reference/sessions/delete-a-session"}]}]}]}]},{"language":"es","pages":[{"title":"es","href":"/es"}]}]},"title":"Obtain a response from an NPC character - NPC Builder","buildId":"dpl_849ArpqvBiCczQiT1Y1stNGpbqHT","deploymentId":"dpl_849ArpqvBiCczQiT1Y1stNGpbqHT","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-Bbp7I60D.js","utils-C3RIvJha.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-DqD-vLt8.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-B31Loprg.js","snippetPresets-DKpk-b8t.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-Cj65AhOR.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-BXtn5gcC.js","shallow-RY2b03Cp.js","getApiPlaygroundDisplay-B0jeiPk3.js","CodeSnippet-CYgBjjwn.js","CodeSnippets-DOngDrYB.js","Page-n7I5XbKb.js","getPastedJson-DRQbJx-T.js","icon-CQiQCicY.js","MethodPill-BKTLdNtu.js","DuplicateIcon-B9jpAdat.js","createIcon-DCddRrXv.js","DynamicMarkdown-a8hUKrw6.js","SectionHeading-eECVV2eH.js","axios-vUo_bRtp.js","Markdown--GF7ZIpf.js","clsx-DZLdJUrt.js","lib--scc4DXi.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-2LoAhjKH.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-Zwc0ZncM.js"]}