curl --request POST \
--url https://app.npcbuilder.com/api/interactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"conversation_id": "conv_12345",
"character_id": "a96c6161-59f5-40f7-955e-459cd11",
"game_id": "tx65BrETVN2vMrrUIrlV",
"world_id": "PtUYW5bLMZNnXPN8qAUJ",
"messages": [
{
"role": "user",
"content": "Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!"
}
],
"user_context": {
"name": "Juan",
"age": "Adult",
"gender": "Male",
"race": "Human",
"class": "Warrior",
"level": 5,
"status": "Healthy",
"description": "Huele mal, con una gran espada y una herida en el pecho"
}
}
'import requests
url = "https://app.npcbuilder.com/api/interactions"
payload = {
"conversation_id": "conv_12345",
"character_id": "a96c6161-59f5-40f7-955e-459cd11",
"game_id": "tx65BrETVN2vMrrUIrlV",
"world_id": "PtUYW5bLMZNnXPN8qAUJ",
"messages": [
{
"role": "user",
"content": "Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!"
}
],
"user_context": {
"name": "Juan",
"age": "Adult",
"gender": "Male",
"race": "Human",
"class": "Warrior",
"level": 5,
"status": "Healthy",
"description": "Huele mal, con una gran espada y una herida en el pecho"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
conversation_id: 'conv_12345',
character_id: 'a96c6161-59f5-40f7-955e-459cd11',
game_id: 'tx65BrETVN2vMrrUIrlV',
world_id: 'PtUYW5bLMZNnXPN8qAUJ',
messages: [
{
role: 'user',
content: 'Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!'
}
],
user_context: {
name: 'Juan',
age: 'Adult',
gender: 'Male',
race: 'Human',
class: 'Warrior',
level: 5,
status: 'Healthy',
description: 'Huele mal, con una gran espada y una herida en el pecho'
}
})
};
fetch('https://app.npcbuilder.com/api/interactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.npcbuilder.com/api/interactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'conversation_id' => 'conv_12345',
'character_id' => 'a96c6161-59f5-40f7-955e-459cd11',
'game_id' => 'tx65BrETVN2vMrrUIrlV',
'world_id' => 'PtUYW5bLMZNnXPN8qAUJ',
'messages' => [
[
'role' => 'user',
'content' => 'Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!'
]
],
'user_context' => [
'name' => 'Juan',
'age' => 'Adult',
'gender' => 'Male',
'race' => 'Human',
'class' => 'Warrior',
'level' => 5,
'status' => 'Healthy',
'description' => 'Huele mal, con una gran espada y una herida en el pecho'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.npcbuilder.com/api/interactions"
payload := strings.NewReader("{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.npcbuilder.com/api/interactions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.npcbuilder.com/api/interactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}"
response = http.request(request)
puts response.read_body{
"response": "Hola Juan, me llamo Jakinen",
"user_events": [
{
"name": "take",
"item": "sword"
},
{
"name": "dance",
"item": null
}
],
"character_events": [
{
"name": "give",
"item": "shield"
},
{
"name": "attack",
"item": null
}
]
}{
"response": "Hola Juan, me llamo Jakinen",
"user_events": [
{
"name": "take",
"item": "sword"
},
{
"name": "dance",
"item": null
}
]
}"No autorizado, no se proporcionó token""No autorizado, token inválido. Intenta generar un token nuevo.""No hay un contexto de mundo definido.""Error al crear la interacción"Obtener una respuesta de un personaje NPC
Envía un array de mensajes de interacción entre el jugador y el personaje NPC. La API procesa el historial de conversación y devuelve una nueva respuesta generada por el personaje. Modos de respuesta
-
HTTP batch (por defecto): Envía una petición
POST https://app.npcbuilder.com/api/interactions. El servicio compone toda la respuesta y entrega un JSON conresponse,user_eventsycharacter_events. -
Streaming por WebSocket: Abre una conexión WebSocket a
wss://api.app.npcbuilder.com/api/interactions. Una vez aceptada, envía:{ "type": "interaction.start", "payload": { ...interacción... }, "meta": { "language": "es-ES", "session_id": "opcional" } }El servidor emite los eventos
stream.accepted, variosstream.delta, opcionalmentestream.safe_responsecuando se detecta una frase vetada y, al finalizar,stream.endcon el texto completo, los eventos y los tokens consumidos.Envía
{"type":"interaction.cancel"}para abortar una generación.
Complemento de voz (solo WebSocket)
-
Conecta a
wss://api.app.npcbuilder.com/api/interactions?voice=truepara voz bidireccional, o usavoice=input/voice=outputpara voz en un solo sentido. También puedes proporcionarmeta.voicedentro deinteraction.start. - Con voz habilitada se mantienen los eventosstream.*de texto y además se envían eventosvoice.*:voice.ready,voice.session.updated— estado de la sesión de Azure Voice Live.voice.audio.delta,voice.audio.timestamp,voice.audio.done,voice.response.done— audio generado por el asistente.voice.transcript.delta,voice.input.started/stopped,voice.usage— audio del micrófono transcrito por el servicio.
-
Comandos aceptados mientras la sesión está activa:
{ "type": "voice.input.append", "data": { "audio": "<chunk pcm16 base64>" } } { "type": "voice.input.commit" } { "type": "voice.input.clear" } { "type": "voice.session.update", "data": { "voice_name": "en-US-Ava:DragonHDLatestNeural" } } { "type": "voice.cancel" }
El streaming de texto nunca se desactiva: siempre recibirás stream.delta y el stream.end final, incluso cuando la reproducción de voz está activa.
curl --request POST \
--url https://app.npcbuilder.com/api/interactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"conversation_id": "conv_12345",
"character_id": "a96c6161-59f5-40f7-955e-459cd11",
"game_id": "tx65BrETVN2vMrrUIrlV",
"world_id": "PtUYW5bLMZNnXPN8qAUJ",
"messages": [
{
"role": "user",
"content": "Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!"
}
],
"user_context": {
"name": "Juan",
"age": "Adult",
"gender": "Male",
"race": "Human",
"class": "Warrior",
"level": 5,
"status": "Healthy",
"description": "Huele mal, con una gran espada y una herida en el pecho"
}
}
'import requests
url = "https://app.npcbuilder.com/api/interactions"
payload = {
"conversation_id": "conv_12345",
"character_id": "a96c6161-59f5-40f7-955e-459cd11",
"game_id": "tx65BrETVN2vMrrUIrlV",
"world_id": "PtUYW5bLMZNnXPN8qAUJ",
"messages": [
{
"role": "user",
"content": "Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!"
}
],
"user_context": {
"name": "Juan",
"age": "Adult",
"gender": "Male",
"race": "Human",
"class": "Warrior",
"level": 5,
"status": "Healthy",
"description": "Huele mal, con una gran espada y una herida en el pecho"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
conversation_id: 'conv_12345',
character_id: 'a96c6161-59f5-40f7-955e-459cd11',
game_id: 'tx65BrETVN2vMrrUIrlV',
world_id: 'PtUYW5bLMZNnXPN8qAUJ',
messages: [
{
role: 'user',
content: 'Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!'
}
],
user_context: {
name: 'Juan',
age: 'Adult',
gender: 'Male',
race: 'Human',
class: 'Warrior',
level: 5,
status: 'Healthy',
description: 'Huele mal, con una gran espada y una herida en el pecho'
}
})
};
fetch('https://app.npcbuilder.com/api/interactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.npcbuilder.com/api/interactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'conversation_id' => 'conv_12345',
'character_id' => 'a96c6161-59f5-40f7-955e-459cd11',
'game_id' => 'tx65BrETVN2vMrrUIrlV',
'world_id' => 'PtUYW5bLMZNnXPN8qAUJ',
'messages' => [
[
'role' => 'user',
'content' => 'Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!'
]
],
'user_context' => [
'name' => 'Juan',
'age' => 'Adult',
'gender' => 'Male',
'race' => 'Human',
'class' => 'Warrior',
'level' => 5,
'status' => 'Healthy',
'description' => 'Huele mal, con una gran espada y una herida en el pecho'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.npcbuilder.com/api/interactions"
payload := strings.NewReader("{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.npcbuilder.com/api/interactions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.npcbuilder.com/api/interactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"conversation_id\": \"conv_12345\",\n \"character_id\": \"a96c6161-59f5-40f7-955e-459cd11\",\n \"game_id\": \"tx65BrETVN2vMrrUIrlV\",\n \"world_id\": \"PtUYW5bLMZNnXPN8qAUJ\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hola Jakinen, me llamo Juan, ¡cogeré mi espada y bailaré!\"\n }\n ],\n \"user_context\": {\n \"name\": \"Juan\",\n \"age\": \"Adult\",\n \"gender\": \"Male\",\n \"race\": \"Human\",\n \"class\": \"Warrior\",\n \"level\": 5,\n \"status\": \"Healthy\",\n \"description\": \"Huele mal, con una gran espada y una herida en el pecho\"\n }\n}"
response = http.request(request)
puts response.read_body{
"response": "Hola Juan, me llamo Jakinen",
"user_events": [
{
"name": "take",
"item": "sword"
},
{
"name": "dance",
"item": null
}
],
"character_events": [
{
"name": "give",
"item": "shield"
},
{
"name": "attack",
"item": null
}
]
}{
"response": "Hola Juan, me llamo Jakinen",
"user_events": [
{
"name": "take",
"item": "sword"
},
{
"name": "dance",
"item": null
}
]
}"No autorizado, no se proporcionó token""No autorizado, token inválido. Intenta generar un token nuevo.""No hay un contexto de mundo definido.""Error al crear la interacción"Autorizaciones
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Parámetros de consulta
El código de idioma para la interacción. Valores admitidos: - en-US: Inglés (Estados Unidos) - es-ES: Español (España)
en-US, es-ES "en-US"
(Opcional) El identificador único de la sesión del jugador.
"60Z5aZjIuFlyYbjbZZKe"
Opcional. Controla el complemento de Azure Voice Live cuando se usa WebSocket. Valores aceptados:
false(predeterminado): desactiva la voz. *true: habilita audio bidireccional (STT + TTS). *input: solo captura voz del usuario (STT). *output: solo sintetiza el audio del asistente (TTS).
false, true, input, output Cuerpo
Una carga útil en JSON, XML o codificada en URL que contiene el historial completo de la conversación. Asegúrate de enviar los mensajes como un array de objetos siguiendo el esquema definido.
El esquema Interaction define la estructura para una conversación entre un jugador y un NPC. Incluye metadatos como ID del personaje, ID del juego, ID del mundo y un array de mensajes.
(Opcional) El identificador único de la conversación existente para cargar/persistir el historial.
"conv_12345"
El identificador único del personaje NPC.
"a96c6161-59f5-40f7-955e-459cd11"
El identificador único del juego.
"tx65BrETVN2vMrrUIrlV"
El identificador único del mundo.
"PtUYW5bLMZNnXPN8qAUJ"
Un array de mensajes intercambiados entre el jugador y el NPC.
Show child attributes
Show child attributes
Un objeto que contiene información específica del jugador para el contexto del personaje.
Show child attributes
Show child attributes
Respuesta
Operación exitosa. Devuelve la respuesta del personaje junto con cualquier evento de usuario desencadenado.
El esquema ApiResponse representa la respuesta correcta de la API, incluyendo la respuesta del NPC y cualquier evento desencadenado por el usuario.