API Documentation
Contents
Quick Start
Get an NPC talking in under 60 seconds:
Or use MCP for Claude Code native integration: ainpc mcp-serve | View on npm
Authentication
CLI (recommended): Headers are automatic after login.
ainpc login --key YOUR_KEY --game my-rpg # All subsequent commands auto-include credentials
REST API (direct): Two headers required on every request:
| Header | Description |
|---|---|
x-api-key | Your API key |
x-game-id | Your game identifier (tenant isolation) |
Create NPC
POST /api/npcs
{
"name": "Grok the Blacksmith",
"role": "merchant",
"faction": "village_guard",
"location": "blacksmith_shop",
"personality": {
"traits": ["gruff", "honest", "protective"],
"speechStyle": "gruff",
"backstory": "Former soldier who retired to smithing",
"values": ["honor", "craft", "family"],
"quirks": ["always mentions the weather"]
},
"inventory": [
{ "item": "iron_sword", "price": 50, "quantity": 2 },
{ "item": "shield", "price": 30, "quantity": 1 }
]
}
Send Event
POST /api/npcs/:npcId/event
{
"type": "player_dialogue",
"playerId": "player_joe",
"message": "Do you have any swords for sale?",
"context": {
"location": "blacksmith_shop",
"timeOfDay": "morning",
"weather": "sunny",
"playerReputation": 75,
"playerLevel": 12
}
}
Response:
{
"response": {
"dialogue": "Aye lad, got a fine iron blade. Fifty gold.",
"emotion": "cheerful",
"action": { "type": "gesture", "target": "display_rack" },
"tradeOffer": { "item": "iron_sword", "price": 45 },
"memoryUpdated": true
},
"tokenUsage": { "input": 1200, "output": 85, "calls": 1 }
}
Errors: unknown npcId returns 404 { "error": "NPC not found" }. If experts are unavailable or all fail, the response includes an error field ({ "code": "no_experts" | "experts_failed", "message": "..." }) alongside a fallback response — check it to distinguish an outage from a quiet NPC.
WebSocket
Connect to ws://host:port/ws?apiKey=xxx&gameId=yyy
Send events:
{ "action": "event", "data": { "type": "player_dialogue", "npcId": "...", "message": "...", "context": {...} } }
{ "action": "subscribe", "npcIds": ["npc1", "npc2"] }
Update NPC
PATCH /api/npcs/:npcId — Update any NPC properties (partial update).
curl -X PATCH http://localhost:18542/api/npcs/{npcId} \
-H "x-api-key: your-key" \
-H "x-game-id: my-game" \
-H "Content-Type: application/json" \
-d '{"location": "town_square", "mood": {"emotion": "angry", "intensity": 0.8, "cause": "theft"}}'
Generate NPC
POST /api/npcs/generate — AI-generate an NPC with full persona, psychology, and schedule.
curl -X POST http://localhost:18542/api/npcs/generate \
-H "x-api-key: your-key" \
-H "x-game-id: my-game" \
-H "Content-Type: application/json" \
-d '{"role": "merchant", "name": "Grok"}'
Returns a full NPC with cognitive extensions: persona (OCEAN personality, backstory, fears, ambitions), schedule (daily routines), and psychology (stress, trauma, goals, emotions).
Batch Generate
POST /api/npcs/generate-batch — Generate multiple NPCs with social relationships.
curl -X POST http://localhost:18542/api/npcs/generate-batch \
-H "x-api-key: your-key" \
-H "x-game-id: my-game" \
-H "Content-Type: application/json" \
-d '{"count": 5, "role": "guard"}'
Returns { npcs: [...], socialLinks: [...] } — NPCs plus auto-generated relationships between them.
Batch Events
POST /api/events — Send multiple events in one request.
{
"events": [
{ "type": "player_dialogue", "npcId": "npc1", "playerId": "p1", "message": "Hello!", "context": {...} },
{ "type": "player_approached", "npcId": "npc2", "playerId": "p1", "context": {...} }
]
}
Returns { results: [EventResult, ...] } — one result per event, in order. Batch results are always 200; per-event failures (e.g. unknown npcId) are flagged via the result's error field ({ "code": "npc_not_found", ... }).
Unity SDK
Copy sdk/unity/ into Assets/Plugins/AINPCEngine/
var client = new NPCEngineClient("http://localhost:18542", "key", "my-game");
// Talk to an NPC
var result = await client.Say(npcId, "player1", "Hello!", context);
Debug.Log(result.response.dialogue);
// AI-generate an NPC with full persona
var npc = await client.GenerateNPC(new GenerateNPCRequest { role = "merchant" });
// Batch-generate NPCs with relationships
var batch = await client.GenerateBatch(new GenerateBatchRequest { count = 5, role = "guard" });
// Send batch events
var results = await client.SendBatchEvents(new BatchEventItem[] { ... });
git clone https://github.com/jyswee/ainpc-unity-demo.git
View on GitHub
Unreal SDK
Copy sdk/unreal/AINPCEngine/ into your project's Plugins/ folder and enable in the Plugin Manager.
// Create client
UNPCEngineClient* Client = NewObject<UNPCEngineClient>();
Client->Init("http://localhost:18542", "key", "my-game");
// Bind response delegate
Client->OnEventResult.AddDynamic(this, &AMyActor::OnNPCResponse);
// Talk to an NPC
FGameContext Context;
Context.Location = "blacksmith_shop";
Context.TimeOfDay = "morning";
Client->Say(NpcId, "player1", "Got any swords?", Context);
// AI-generate an NPC
FGenerateNPCRequest GenReq;
GenReq.Role = "merchant";
Client->GenerateNPC(GenReq);
Full Blueprint support — all methods are BlueprintCallable and responses fire BlueprintAssignable delegates.
git clone https://github.com/jyswee/ainpc-unreal-demo.git
View on GitHub
Godot SDK
Copy sdk/godot/addons/ainpcengine/ into your project's addons/ folder. Enable in Project → Project Settings → Plugins.
var client = AINPCEngineClient.new()
client.setup("http://localhost:18542", "key", "my-game")
add_child(client)
# Talk to an NPC
var context = AINPCModels.game_context("blacksmith", "morning", "sunny")
var result = await client.say(npc_id, "player1", "Got any swords?", context)
print(result.response.dialogue)
# AI-generate an NPC
var npc = await client.generate_npc("merchant", "Grok")
# Batch-generate NPCs with relationships
var batch = await client.generate_batch(5, "guard")
Uses Godot 4 await pattern. WebSocket client available via AINPCWebSocket class for real-time streaming.
git clone https://github.com/jyswee/ainpc-godot-demo.git
View on GitHub
Rust SDK
Add to your Cargo.toml:
[dependencies]
ainpc-sdk = { git = "https://github.com/jyswee/ainpc-rust-sdk.git" }
use ainpc_sdk::{AINPCClient, GameContext};
#[tokio::main]
async fn main() {
let client = AINPCClient::new("http://localhost:18542", "key", "my-game");
// Talk to an NPC
let result = client.say("npc_1", "player_1", "Hello!", GameContext {
location: Some("village".into()),
time_of_day: Some("morning".into()),
weather: Some("sunny".into()),
player_reputation: 75,
player_level: 5,
..Default::default()
}).await.unwrap();
println!("NPC: {}", result.response.dialogue.unwrap_or_default());
}
Full REST client + WebSocket support. WASM-compatible (gate WebSocket behind native feature).
git clone https://github.com/jyswee/ainpc-rust-sdk.git
View on GitHub
Node.js / REST API
No SDK needed - use any HTTP client. All endpoints accept JSON with x-api-key and x-game-id headers.
const API = "https://ainpcengine.com/api";
const HEADERS = {
"Content-Type": "application/json",
"x-api-key": "your-api-key",
"x-game-id": "my-game"
};
// Create an NPC
const npc = await fetch(`${API}/npcs`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
name: "Grok", role: "blacksmith",
personality: {
traits: ["gruff", "loyal"],
speechStyle: "blunt, short sentences",
backstory: "Third-gen smith",
values: ["craftsmanship", "honor"],
quirks: []
}
})
}).then(r => r.json());
// Talk to the NPC
const result = await fetch(`${API}/npcs/${npc.id}/event`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
type: "player_dialogue",
playerId: "player_1",
message: "Got any swords?",
context: { location: "forge", timeOfDay: "morning" }
})
}).then(r => r.json());
console.log(result.response.dialogue);
Works with Node.js, Python, Go, or any language with HTTP support. See Agent Quickstarts for AI coding agent integration.
CLI (npm)
Command-line interface for coding agents and quick testing. Zero dependencies.
npm install -g ainpc-cli # Setup ainpc login --key YOUR_KEY --game my-rpg # Create NPC ainpc create "Grok" --role merchant --traits gruff,loyal # Talk to NPC ainpc say NPC_ID "Got any swords?" # AI-generate full NPC (NPC Persona) ainpc generate --role guard # List all NPCs ainpc list # NPC voice synthesis ainpc speak NPC_ID "Welcome, traveler" # Full reference ainpc --help
Config stored in .ainpc/config.json (project-local) or ~/.ainpc/config.json (global). Supports --json flag for machine-readable output.
Use the ainpc CLI for NPC management. Config auto-loaded from .ainpc/config.json or AINPC_API_KEY env.
View on npm
Event Types
| Event | Experts | Use When |
|---|---|---|
player_approached | Dialogue + Social | Player enters NPC range |
player_dialogue | Dialogue | Player speaks to NPC |
combat_started | Combat + Dialogue | Fight begins |
trade_requested | Trade + Dialogue | Player wants to buy/sell |
quest_accepted | Quest + Dialogue | Player takes a quest |
quest_completed | Quest + Social + Dialogue | Player finishes quest |
ambient_trigger | Ambient | Idle/background behavior |
world_event | Ambient + Social | Weather change, explosion, etc. |
npc_interaction | Social + Dialogue | NPC-to-NPC interaction |
<custom> | Dialogue | Any custom type string (e.g. bigHand, blunder) — routes to the Dialogue expert and stays in-character |
context to make the NPC react in-character to a specific beat on any event type:
context.situation— what is happening right now, in plain text (e.g."Joe just made a slam on 6S — react big"). This anchors the scene.context.style— a per-event voice/style directive that reinforces the seeded personality (e.g."ALL-CAPS machine voice; arcade card game, never mention fantasy").context.playerName— display name to address the player by (playerIdstays the stable memory key).context.language— per-event output language as a BCP-47 tag (e.g."en","vi","pt-BR"). Omit and the NPC infers its own language from the persona; set it and the NPC is hard-pinned to that language for this event. The same NPC can speak its native language on one surface and English on another without forking its memory.
DELETE your pilot NPCs and re-create them, rather than promoting the ones you tested with.