Skip to Content
Loremind Platform APIServer Integration

Server Integration Guide

This guide shows how to integrate LoreMind with popular backend platforms. Choose the pattern that matches your stack.

Why Use a Backend?

Your backend:

  • Keeps API keys secure - Never expose keys in game builds
  • Identifies players - Provide playerId for long-term memory and per-player rate limits
  • Adds your own logic - Custom rate limiting, validation, logging, analytics

Important: The LoreMind API key must never be in your game client. Only your backend should have it.

See Backend Integration for a simpler getting-started guide.


Nakama (TypeScript)

Nakama  is an open-source game server supporting realtime multiplayer, matchmaking, and server-side logic. LoreMind integrates via Nakama’s TypeScript runtime.

Register the RPC

// main.ts const InitModule: nkruntime.InitModule = function( ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, initializer: nkruntime.Initializer ) { initializer.registerRpc('npc_interact', rpcNpcInteract); logger.info('LoreMind NPC module loaded'); }; const LOREMIND_URL = 'https://loremind.peekgames.dev/api/loremind/v1/npc/interact'; const LOREMIND_API_KEY = 'sk_server_your_key_here'; // Use env var in production

NPC Interaction RPC

const rpcNpcInteract: nkruntime.RpcFunction = function( ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, payload: string ): string { const request = JSON.parse(payload); const playerId = ctx.userId; // Nakama user ID from authenticated session // Client sends context from Unity scene - server just forwards it const body = JSON.stringify({ text: request.message, entityMindId: request.entityMindId, playerId: playerId, // Server provides authenticated player ID memory: { retrieve: true }, context: request.context // Context comes from client (LocationZone, ContextTag, etc.) }); // Call LoreMind API const response = nk.httpRequest(LOREMIND_URL, 'post', { 'Content-Type': 'application/json', 'Authorization': `Bearer ${LOREMIND_API_KEY}` }, body, 30000); if (response.code !== 200) { logger.error(`LoreMind error: ${response.code} ${response.body}`); throw new Error('NPC service unavailable'); } const result = JSON.parse(response.body); logger.info(`NPC response for ${playerId}: ${result.metadata?.creditsUsed} credits`); return JSON.stringify({ response: result.response, character: result.character }); };

Unity Client (with Nakama)

The client gathers context from the scene using SDK components (LocationZone, ContextTag, etc.) and sends it to the server:

using Nakama; using Peek.LoreMind; public class NpcClient : MonoBehaviour { private IClient _client; private ISession _session; [SerializeField] private LoreMindNPC npc; public async Task<string> TalkToNpc(string message) { // Client builds context from scene state var payload = new { entityMindId = npc.EntityMindId, message = message, context = new { location = npc.Context.location, locationDetails = npc.Context.locationDetails, timeOfDay = npc.Context.timeOfDay, weather = npc.Context.weather, nearbyCharacters = npc.Context.nearbyCharacters, playerAppearance = npc.Context.playerAppearance, recentEvents = npc.Context.recentEvents } }; var response = await _client.RpcAsync(_session, "npc_interact", JsonConvert.SerializeObject(payload)); var result = JsonConvert.DeserializeObject<NpcResponse>(response.Payload); return result.response; } }

Resources:


PlayFab CloudScript

PlayFab  is Microsoft’s game backend with CloudScript for server-side logic.

CloudScript Function

// LoreMindNpc.js - PlayFab CloudScript handlers.NpcInteract = function(args, context) { const playerId = context.CallerEntityProfile.EntityId; // Client sends context from Unity scene - server adds playerId and forwards const requestBody = { text: args.message, entityMindId: args.entityMindId, playerId: playerId, // Server provides authenticated player ID memory: { retrieve: true }, context: args.context // Context comes from client }; const response = http.request( 'https://loremind.peekgames.dev/api/loremind/v1/npc/interact', 'POST', JSON.stringify(requestBody), 'application/json', { 'Authorization': 'Bearer ' + GetSecretValue('LOREMIND_API_KEY') } ); if (response.responseCode !== 200) { log.error('LoreMind error: ' + response.responseBody); return { error: 'NPC_UNAVAILABLE' }; } const result = JSON.parse(response.responseBody); // Track credits used server.WritePlayerEvent({ PlayFabId: playerId, EventName: 'npc_interaction', Body: { npcId: args.entityMindId, creditsUsed: result.metadata?.creditsUsed } }); return { response: result.response, character: result.character }; };

Unity Client (with PlayFab)

using PlayFab; using PlayFab.CloudScriptModels; using Peek.LoreMind; public class NpcClient : MonoBehaviour { [SerializeField] private LoreMindNPC npc; public async Task<string> TalkToNpc(string message) { // Client builds context from scene state var request = new ExecuteFunctionRequest { FunctionName = "NpcInteract", FunctionParameter = new { entityMindId = npc.EntityMindId, message = message, context = new { location = npc.Context.location, locationDetails = npc.Context.locationDetails, timeOfDay = npc.Context.timeOfDay, nearbyCharacters = npc.Context.nearbyCharacters, playerAppearance = npc.Context.playerAppearance } } }; var tcs = new TaskCompletionSource<string>(); PlayFabCloudScriptAPI.ExecuteFunction(request, result => { var response = JsonConvert.DeserializeObject<NpcResponse>( result.FunctionResult.ToString()); tcs.SetResult(response.response); }, error => tcs.SetException(new Exception(error.ErrorMessage)) ); return await tcs.Task; } }

Resources:


Custom Node.js

For studios with custom backends using Express, Fastify, or similar frameworks.

Express Server

// server.ts import express from 'express'; import { createClient } from 'redis'; const app = express(); const redis = createClient(); const LOREMIND_API_KEY = process.env.LOREMIND_API_KEY; app.use(express.json()); // Your auth middleware (Steam, Epic, custom JWT) app.use('/api/npc', authenticatePlayer); app.post('/api/npc/interact', async (req, res) => { const playerId = req.player.id; // From your auth middleware const { entityMindId, message, context } = req.body; // Context comes from client // Rate limiting const rateKey = `npc:rate:${playerId}`; const count = await redis.incr(rateKey); if (count === 1) await redis.expire(rateKey, 60); if (count > 10) { return res.status(429).json({ error: 'RATE_LIMITED' }); } // Client sends context from Unity scene - server adds playerId and forwards const response = await fetch( 'https://loremind.peekgames.dev/api/loremind/v1/npc/interact', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${LOREMIND_API_KEY}` }, body: JSON.stringify({ text: message, entityMindId: entityMindId, playerId: playerId, // Server provides authenticated player ID memory: { retrieve: true }, context: context // Context comes from client }) } ); if (!response.ok) { console.error('LoreMind error:', await response.text()); return res.status(503).json({ error: 'NPC_UNAVAILABLE' }); } const result = await response.json(); // Analytics analytics.track('npc_interaction', { playerId, entityMindId, creditsUsed: result.metadata?.creditsUsed }); res.json({ response: result.response, character: result.character }); });

Mirror + Custom Backend

For games using Mirror  networking with a backend that calls external APIs.

Backend Service (C#)

// NpcService.cs - runs on your backend public class NpcService { private readonly HttpClient _http; public NpcService(string apiKey) { _http = new HttpClient { BaseAddress = new Uri("https://loremind.peekgames.dev/api/loremind/v1/"), Timeout = TimeSpan.FromSeconds(30) }; _http.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}"); } public async Task<NpcResponse> GetResponse(NpcRequest request) { // Client sends context - server adds playerId and forwards var payload = new { text = request.Message, entityMindId = request.EntityMindId, playerId = request.PlayerId, // Server provides authenticated player ID memory = new { retrieve = true }, context = request.Context // Context comes from client }; var json = JsonSerializer.Serialize(payload); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _http.PostAsync("npc/interact", content); var body = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { Debug.LogError($"LoreMind error: {response.StatusCode} {body}"); return null; } return JsonSerializer.Deserialize<NpcResponse>(body); } }

Mirror NetworkBehaviour

// NpcInteraction.cs using Peek.LoreMind; public class NpcInteraction : NetworkBehaviour { [SerializeField] private LoreMindNPC npc; private static NpcService _npcService; [Server] public static void InitializeService(string apiKey) { _npcService = new NpcService(apiKey); } // Client calls this Command, sending context from their scene [Command] public void CmdTalkToNpc(string message, RuntimeContext context) { var player = connectionToClient.identity.GetComponent<Player>(); StartCoroutine(HandleNpcRequest(player, message, context)); } [Server] private IEnumerator HandleNpcRequest(Player player, string message, RuntimeContext context) { var request = new NpcRequest { PlayerId = player.PlayerId, EntityMindId = npc.EntityMindId, Message = message, Context = context // Context came from client }; var task = _npcService.GetResponse(request); yield return new WaitUntil(() => task.IsCompleted); if (task.Result != null) { TargetReceiveResponse(connectionToClient, task.Result.response); } else { TargetReceiveResponse(connectionToClient, "*The character doesn't respond*"); } } [TargetRpc] private void TargetReceiveResponse(NetworkConnection conn, string response) { DialogueUI.Instance.ShowResponse(response); } } // Client-side: gather context and send to server public class NpcInteractionClient : MonoBehaviour { [SerializeField] private LoreMindNPC npc; [SerializeField] private NpcInteraction networkNpc; public void TalkToNpc(string message) { // Client builds context from scene state and sends to server networkNpc.CmdTalkToNpc(message, npc.Context); } }

Resources:


API Reference

Request Format

POST https://loremind.peekgames.dev/api/loremind/v1/npc/interact Authorization: Bearer sk_server_... Content-Type: application/json { "text": "What can you tell me about the dragon?", "entityMindId": "em_blacksmith_grom", "playerId": "steam_76561198012345678", "memory": { "retrieve": true }, "context": { "location": "Blacksmith Shop", "timeOfDay": "evening", "weather": "rainy", "playerReputation": "trusted ally", "recentEvents": ["Dragon spotted near village"] } }

Response Format

{ "success": true, "response": "The dragon? Aye, I've heard the rumors...", "character": "Grom the Blacksmith", "metadata": { "creditsUsed": 0.45, "creditsRemaining": 9543.20, "memoriesRetrieved": 2, "memoriesStored": 1 } }

Next Steps

Last updated on