Skip to content

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

ParameterDescriptionExample
pagePage number?page=2
per_pageItems per page (max 100)?per_page=50
seedRandom seed for determinism?seed=12345
localeOverride locale?locale=en_US
formatResponse 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 records

Single 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 stream

Error 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/orders

Custom Domains (Business tier)

https://api-staging.yourcompany.com/users
  └── CNAME → mock.phony.cloud
  └── Routes to ep_abc123

Multi-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_006

Caching 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

MetricValue
Cold start< 50ms
Warm response< 20ms
Throughput10,000 req/sec per endpoint
Max response size10MB
Max records per request10,000

Rate Limits

TierRequests/minBandwidth/day
Free100100 MB
Starter1,0001 GB
Team10,00010 GB
Business100,000100 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/users

Local mode uses the same Rust core as cloud, ensuring identical behavior.

Phony Cloud Platform Specification