Mock API Architecture
Phony's Mock API system generates dynamic REST APIs from PDL schemas, enabling frontend development and integration testing without backend dependencies.
Architecture Overview
┌─────────────────────────────────────────────────────────────────────────┐
│ MOCK API ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ CLIENT REQUEST │
│ ══════════════ │
│ GET https://mock.phony.cloud/ep_abc123/api/users?page=1 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐│
│ │ EDGE (Cloudflare) ││
│ │ • TLS Termination ││
│ │ • DDoS Protection ││
│ │ • Response Caching (when enabled) ││
│ │ • Geographic routing ││
│ └───────────────────────────────┬─────────────────────────────────────┘│
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐│
│ │ MOCK API SERVER (Go) ││
│ │ ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ Router │ │ Schema │ │ Response │ ││
│ │ │ │─►│ Loader │─►│ Generator │ ││
│ │ │ /ep_{id}/* │ │ │ │ │ ││
│ │ └─────────────┘ └─────────────┘ └──────┬──────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌─────────────┐ ││
│ │ │ Rust Core │ ││
│ │ │ (N-gram) │ ││
│ │ │ 5M rec/s │ ││
│ │ └─────────────┘ ││
│ │ ││
│ └─────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ▼ │
│ RESPONSE │
│ ════════ │
│ { │
│ "data": [ │
│ { "id": "usr_abc", "name": "Mehmet", "email": "m@ex.com" }, │
│ { "id": "usr_def", "name": "Ayşe", "email": "a@ex.com" } │
│ ], │
│ "meta": { "page": 1, "total": 100 } │
│ } │
│ │
└─────────────────────────────────────────────────────────────────────────┘Endpoint Configuration
Schema-Driven Endpoints
Each endpoint is defined by a PDL schema:
json
{
"endpoint": {
"path": "/api/users",
"method": "GET",
"description": "List users with pagination"
},
"schema": {
"generators": {
"id": {
"type": "logic",
"algorithm": "uuid_v7"
},
"name": {
"type": "model",
"source": "tr_TR/full_names",
"generation": { "mode": "word" }
},
"email": {
"type": "template",
"pattern": "{{lowercase(name)}}@example.com",
"unique": true
},
"created_at": {
"type": "logic",
"algorithm": "datetime_between",
"params": { "start": "-1year", "end": "now" }
}
},
"output": ["id", "name", "email", "created_at"]
},
"response": {
"wrapper": {
"data": "{{records}}",
"meta": {
"page": "{{query.page | default: 1}}",
"per_page": "{{query.per_page | default: 20}}",
"total": "{{total}}"
}
},
"count": "{{query.per_page | default: 20}}",
"seed": "{{query.seed | default: null}}"
}
}Dynamic Path Parameters
json
{
"endpoint": {
"path": "/api/users/:id",
"method": "GET"
},
"response": {
"count": 1,
"seed": "{{params.id}}"
}
}When accessing /api/users/123, the seed 123 ensures deterministic output - same ID always returns same user.
Request Handling
Query Parameters
| Parameter | Description | Example |
|---|---|---|
page | Page number | ?page=2 |
per_page | Items per page (max 100) | ?per_page=50 |
seed | Random seed for determinism | ?seed=12345 |
locale | Override locale | ?locale=en_US |
format | Response format | ?format=csv |
Request Body (POST/PUT)
For mutation endpoints, request body can influence response:
json
// POST /api/users
// Request:
{
"name": "Custom Name"
}
// Response includes submitted data + generated fields:
{
"id": "usr_generated",
"name": "Custom Name",
"email": "custom.name@example.com",
"created_at": "2026-01-31T10:00:00Z"
}Response Modes
List Mode
GET /api/users
→ Returns array of generated recordsSingle Mode
GET /api/users/:id
→ Returns single record (deterministic by ID)Streaming Mode (Large datasets)
GET /api/users?format=ndjson&count=10000
→ Returns newline-delimited JSON streamError Simulation
json
{
"simulation": {
"error_rate": 0.05,
"errors": [
{ "status": 500, "body": { "error": "Internal server error" }, "weight": 70 },
{ "status": 503, "body": { "error": "Service unavailable" }, "weight": 30 }
],
"latency": {
"min_ms": 50,
"max_ms": 200,
"p99_ms": 500
}
}
}Routing Architecture
URL Structure
https://mock.phony.cloud/{endpoint_id}/{path}
Examples:
https://mock.phony.cloud/ep_abc123/api/users
https://mock.phony.cloud/ep_abc123/api/users/456
https://mock.phony.cloud/ep_abc123/api/ordersCustom Domains (Business tier)
https://api-staging.yourcompany.com/users
└── CNAME → mock.phony.cloud
└── Routes to ep_abc123Multi-Endpoint Projects
A project can have multiple endpoints sharing the same base URL:
Project: "E-Commerce API"
├── GET /api/users → ep_001
├── GET /api/users/:id → ep_002
├── POST /api/users → ep_003
├── GET /api/products → ep_004
├── GET /api/orders → ep_005
└── GET /api/orders/:id/items → ep_006Caching Strategy
┌─────────────────────────────────────────────────────────────────────────┐
│ CACHING LAYERS │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ LAYER 1: Edge Cache (Cloudflare) │
│ ═══════════════════════════════ │
│ • Cache-Control: public, max-age=60 (when seed provided) │
│ • Cache key: URL + seed parameter │
│ • Bypass: No seed = no edge cache │
│ │
│ LAYER 2: Response Cache (Redis) │
│ ═══════════════════════════════ │
│ • Schema hash + seed → cached response │
│ • TTL: 5 minutes │
│ • Invalidated on schema update │
│ │
│ LAYER 3: Schema Cache (Memory) │
│ ══════════════════════════════ │
│ • Loaded PDL schemas cached in memory │
│ • Refreshed on update webhook │
│ │
│ CACHE BEHAVIOR: │
│ ════════════════ │
│ ?seed=123 → Fully cacheable (same output every time) │
│ (no seed) → Fresh generation on each request │
│ │
└─────────────────────────────────────────────────────────────────────────┘CORS Configuration
json
{
"cors": {
"enabled": true,
"origins": ["*"],
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
"headers": ["Content-Type", "Authorization", "X-Request-ID"],
"credentials": false,
"max_age": 86400
}
}For production, restrict origins:
json
{
"cors": {
"origins": [
"https://app.yourcompany.com",
"http://localhost:3000"
]
}
}Authentication Simulation
API Key
json
{
"auth": {
"type": "api_key",
"header": "X-API-Key",
"valid_keys": ["test_key_123", "dev_key_456"],
"error_response": {
"status": 401,
"body": { "error": "Invalid API key" }
}
}
}Bearer Token
json
{
"auth": {
"type": "bearer",
"tokens": ["token_abc", "token_def"],
"jwt_validation": {
"enabled": true,
"issuer": "https://auth.yourcompany.com",
"audience": "api"
}
}
}Webhook Integration
On-Request Webhooks
Forward requests to your system for logging/debugging:
json
{
"webhooks": {
"on_request": {
"url": "https://yourapp.com/webhook/mock-request",
"include": ["headers", "query", "body"],
"async": true
}
}
}Request Logging
All requests are logged and available in dashboard:
json
{
"request_id": "req_abc123",
"endpoint_id": "ep_def456",
"method": "GET",
"path": "/api/users",
"query": { "page": "1" },
"response_time_ms": 45,
"status": 200,
"timestamp": "2026-01-31T10:00:00Z"
}Performance
| Metric | Value |
|---|---|
| Cold start | < 50ms |
| Warm response | < 20ms |
| Throughput | 10,000 req/sec per endpoint |
| Max response size | 10MB |
| Max records per request | 10,000 |
Rate Limits
| Tier | Requests/min | Bandwidth/day |
|---|---|---|
| Free | 100 | 100 MB |
| Starter | 1,000 | 1 GB |
| Team | 10,000 | 10 GB |
| Business | 100,000 | 100 GB |
Local Development
Run mock API locally using the CLI:
bash
# Start local mock server
phony mock start --schema api.pdl.json --port 3000
# Output:
# Mock API running at http://localhost:3000
# Endpoints:
# GET /api/users
# GET /api/users/:id
# POST /api/usersLocal mode uses the same Rust core as cloud, ensuring identical behavior.