Documentation
llmplaceholder is a mock LLM API server. Point your app at it instead of OpenAI or Anthropic — no real API key needed. Responses are deterministic and configurable.
Create a tenant
A tenant is your mock "environment". Each one has its own responses, tools, and state.
Set X-Tenant-ID
Add the header to your app's API calls. All LLM and MCP endpoints are tenant-scoped.
Get mock responses
Keyword matching picks the right scenario. No scenarios? A generic placeholder responds.
curl -X POST http://localhost:8080/v1/chat/completions \
-H "X-Tenant-ID: my-app" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"hello"}]}'
Tenants
Isolated mock environments. Create one per app, test case, or team.
Creating a tenant
Use the Playground UI or the API. Tenant IDs can be any string.
curl -X POST http://localhost:8080/public/tenants \
-H "Content-Type: application/json" \
-d '{"tenant_id": "my-app"}'
Using a tenant
Pass X-Tenant-ID on every request. That's it.
# OpenAI-compatible curl -X POST .../v1/chat/completions -H "X-Tenant-ID: my-app" ... # Anthropic-compatible curl -X POST .../v1/messages -H "X-Tenant-ID: my-app" ... # MCP curl -X POST .../mcp/message -H "X-Tenant-ID: my-app" ...
Global tenants
Pre-built tenants (e.g. tenant_ecommerce, saas-demo). Read-only. Available to everyone.
Private tenants
Created by you after login. Full control — edit state, scenarios, tools, and chaos.
Scenarios
Map keywords to responses. When a message contains your keyword, that response is returned.
How matching works
The incoming message is scanned for keywords (case-insensitive). First match wins. If nothing matches, a generic response is returned.
"Show me recent invoices"
"invoice"
→ match
Your configured response text
Adding a scenario via API
curl -X POST http://localhost:8080/public/tenants/my-app/scenarios \
-H "Content-Type: application/json" \
-d '{
"keywords": ["invoice", "billing"],
"response": "Here are your recent invoices: INV-001 ($120), INV-002 ($85)."
}'
Built-in scenarios
Each tenant domain (e.g. ecommerce, SaaS) comes with pre-loaded scenarios. Browse them in Playground → Tenants → Scenarios tab.
MCP Tools
Mock any MCP tool call. Your app calls tools/call, gets back JSON you define.
tools/list
Returns all tools defined in the tenant's scenarios.
tools/call
Matches by tool name. Returns the mock tool_data from the matching tenant scenario.
Adding a tool via API
curl -X POST http://localhost:8080/public/tenants/my-app/scenarios \
-H "Content-Type: application/json" \
-d '{
"keywords": [],
"response": "",
"tool_name": "get_invoice_list",
"tool_data": {
"type": "object",
"properties": {
"invoices": {"type": "array"}
}
}
}'
Calling the tool
curl -X POST http://localhost:8080/mcp/message \
-H "X-Tenant-ID: my-app" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_invoice_list"}}'
Tenant State
A per-tenant JSON document. Store domain data here — your seeded tenants come pre-populated with realistic state for their domain.
Setting state via API
curl -X PUT http://localhost:8080/public/tenants/my-app/state \
-H "Content-Type: application/json" \
-d '{
"state": {
"mrr_usd": 999,
"churn_rate_pct": 0.1
}
}'
Or use the State tab in Playground — it has a live JSON editor.
State is scoped per tenant — editing one tenant's state has no effect on others.
Persisted in SQLite. Survives server restarts.
Seeded tenants (e.g. tenant_saas_growth) come with realistic state pre-loaded for their domain.
Chaos Testing
Inject faults into your tenant to test how your app handles errors. Set a profile and all requests to that tenant break in that way.
none
Normal operation
Responses work as usual.
rate_limit
Returns HTTP 429
Includes Retry-After header. Tests rate-limit handling.
server_error
Returns HTTP 500
Generic server error JSON. Tests error recovery.
latency
5-second delay
Response arrives after 5 s. Tests timeout handling.
Setting chaos via API
curl -X POST http://localhost:8080/public/tenants/my-app/chaos \
-H "Content-Type: application/json" \
-d '{"profile": "rate_limit"}'
# Reset to normal
curl -X POST http://localhost:8080/public/tenants/my-app/chaos \
-H "Content-Type: application/json" \
-d '{"profile": "none"}'
API Tokens
Generate tokens for programmatic access. Useful for CI pipelines or scripts that need to manage tenants.
Creating a token
Login required. Go to Playground → API Tokens tab.
- Enter a name for the token
- Click Generate
- Copy the token — it's only shown once
Using a token
curl -X POST http://localhost:8080/public/tenants \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" \
-d '{"tenant_id": "ci-test-run-42"}'
Playground
Visual interface for everything. No curl needed.
Test requests
Send live requests to any tenant directly from the browser. Supports OpenAI, Anthropic, and MCP protocols.
Manage tenants
Create, delete, and configure tenants. Each tenant has 4 tabs: State, Scenarios, MCP Tools, and Chaos.
Tenant scenarios
Each seeded tenant comes with domain scenarios (ecommerce, SaaS, DevOps, etc.) scoped to that tenant. Browse them in the Scenarios tab.
Live JSON state editor
Edit tenant state in a text editor and save. Changes take effect immediately on the next request.
Need the full API reference? Routes page →