Files
doorman/user-docs/04-api-workflows.md
2025-12-02 19:19:57 -05:00

16 KiB

API Workflows

End-to-end examples for common API gateway scenarios.

Setup

export BASE=http://localhost:3001
export COOKIE=/tmp/doorman.cookies
export DOORMAN_ADMIN_EMAIL="admin@example.com"
export DOORMAN_ADMIN_PASSWORD="YourStrongPassword123!"

# Login once
curl -sc "$COOKIE" -H 'Content-Type: application/json' \
  -d "{\"email\":\"$DOORMAN_ADMIN_EMAIL\",\"password\":\"$DOORMAN_ADMIN_PASSWORD\"}" \
  "$BASE/platform/authorization"

Workflow 1: REST API with API Key Injection

Goal: Publish /api/rest/customers/v1/*http://httpbin.org with automatic API key injection.

1. Create Token Group

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/credit" -d '{
    "api_credit_group": "demo-customers",
    "api_key": "demo-secret-123",
    "api_key_header": "x-api-key",
    "credit_tiers": [
      {
        "tier_name": "default",
        "credits": 999999,
        "input_limit": 0,
        "output_limit": 0,
        "reset_frequency": "monthly"
      }
    ]
  }'

2. Create API

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/api" -d '{
    "api_name": "customers",
    "api_version": "v1",
    "api_description": "Demo customers API",
    "api_allowed_roles": ["admin"],
    "api_allowed_groups": ["ALL"],
    "api_servers": ["http://httpbin.org"],
    "api_type": "REST",
    "api_allowed_retry_count": 0,
    "api_allowed_headers": ["content-type", "accept"],
    "api_credits_enabled": true,
    "api_credit_group": "demo-customers"
  }'

3. Add Endpoints

# GET endpoint
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/endpoint" -d '{
    "api_name": "customers",
    "api_version": "v1",
    "endpoint_method": "GET",
    "endpoint_uri": "/get",
    "endpoint_description": "Echo GET request"
  }'

# POST endpoint
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/endpoint" -d '{
    "api_name": "customers",
    "api_version": "v1",
    "endpoint_method": "POST",
    "endpoint_uri": "/post",
    "endpoint_description": "Echo POST request"
  }'

4. Subscribe User

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/subscription/subscribe" -d '{
    "username": "admin",
    "api_name": "customers",
    "api_version": "v1"
  }'

5. Test

curl -sb "$COOKIE" "$BASE/api/rest/customers/v1/get?demo=1"

Workflow 2: Client-Specific Routing

Goal: Route clients to different upstream pools via client-key header.

1. Create Routing Entries

# Enterprise client routing
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/routing" -d '{
    "routing_name": "customers-enterprise",
    "routing_servers": ["http://premium-upstream-a:8080", "http://premium-upstream-b:8080"],
    "routing_description": "Premium pool for enterprise clients",
    "client_key": "enterprise-A"
  }'

# Free tier client routing
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/routing" -d '{
    "routing_name": "customers-free",
    "routing_servers": ["http://shared-upstream:8080"],
    "routing_description": "Shared pool for free tier",
    "client_key": "free-tier"
  }'

2. Test

# Enterprise tier
curl -sb "$COOKIE" -H 'client-key: enterprise-A' "$BASE/api/rest/customers/v1/get"

# Free tier
curl -sb "$COOKIE" -H 'client-key: free-tier' "$BASE/api/rest/customers/v1/get"

Workflow 3: Per-User Token Management

Goal: Track per-user credits and inject user-specific API keys.

1. Create Token Group

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/credit" -d '{
    "api_credit_group": "openai-api",
    "api_key": "default-openai-key",
    "api_key_header": "Authorization",
    "credit_tiers": [
      {
        "tier_name": "free",
        "credits": 1000,
        "input_limit": 100,
        "output_limit": 100,
        "reset_frequency": "monthly"
      },
      {
        "tier_name": "premium",
        "credits": 100000,
        "input_limit": 10000,
        "output_limit": 10000,
        "reset_frequency": "monthly"
      }
    ]
  }'

Step 2: Assign User-Specific API Key

User-specific keys override the group default.

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/credit/alice" -d '{
    "api_credit_group": "openai-api",
    "api_key": "ALICE-PERSONAL-OPENAI-KEY",
    "api_key_header": "Authorization",
    "credit_tiers": [
      {
        "tier_name": "premium",
        "credits": 100000,
        "input_limit": 10000,
        "output_limit": 10000,
        "reset_frequency": "monthly"
      }
    ]
  }'

Step 3: Create API with Credits Enabled

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/api" -d '{
    "api_name": "openai",
    "api_version": "v1",
    "api_description": "OpenAI API proxy",
    "api_allowed_roles": ["user", "admin"],
    "api_allowed_groups": ["ALL"],
    "api_servers": ["https://api.openai.com"],
    "api_type": "REST",
    "api_credits_enabled": true,
    "api_credit_group": "openai-api",
    "api_allowed_headers": ["content-type", "authorization"]
  }'

Step 4: Call Gateway

When Alice calls the gateway:

  • Doorman injects her personal API key
  • Deducts credits from her account
  • Returns 401 with error code GTW008 when credits run out
# Alice's call (uses her personal key and credits)
curl -s -b "$COOKIE" -H 'Content-Type: application/json' \
  -d '{"prompt": "Hello world"}' \
  "$BASE/api/rest/openai/v1/completions"

Credit tracking:

  • Input/output tokens counted against limits
  • Credits reset based on reset_frequency
  • View credit usage via /platform/credit/{username}

Workflow 4: GraphQL Gateway

Scenario: Proxy a public GraphQL API with optional validation.

Gateway path: /api/graphql/{apiName}

Required header: X-API-Version: v1

Step 1: Create GraphQL API

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/api" -d '{
    "api_name": "countries",
    "api_version": "v1",
    "api_description": "Public GraphQL API for country data",
    "api_allowed_roles": ["admin", "user"],
    "api_allowed_groups": ["ALL"],
    "api_servers": ["https://countries.trevorblades.com"],
    "api_type": "GraphQL",
    "api_allowed_headers": ["content-type"],
    "api_allowed_retry_count": 0
  }'

Step 2: Subscribe User

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/subscription/subscribe" -d '{
    "username": "admin",
    "api_name": "countries",
    "api_version": "v1"
  }'

Step 3: Call GraphQL Gateway

curl -s -b "$COOKIE" \
  -H 'Content-Type: application/json' \
  -H 'X-API-Version: v1' \
  -d '{"query":"{ country(code: \"US\") { name capital currency } }"}' \
  "$BASE/api/graphql/countries"

Optional: Add GraphQL validation

Attach validation to verify operation shape and variables:

{
  "api_validation_enabled": true,
  "api_validation_schema": {
    "query": {"required": true, "type": "string"},
    "variables": {"required": false, "type": "object"}
  }
}

Workflow 5: SOAP Gateway

Scenario: Proxy legacy SOAP APIs with XML validation.

Gateway path: /api/soap/{path}

Step 1: Create SOAP API

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/api" -d '{
    "api_name": "legacy-orders",
    "api_version": "v1",
    "api_description": "Legacy SOAP order service",
    "api_allowed_roles": ["admin"],
    "api_allowed_groups": ["internal"],
    "api_servers": ["http://legacy-soap.internal:8080"],
    "api_type": "SOAP",
    "api_allowed_retry_count": 1,
    "api_allowed_headers": ["content-type", "soapaction"]
  }'

Step 2: Add SOAP Endpoints

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/endpoint" -d '{
    "api_name": "legacy-orders",
    "api_version": "v1",
    "endpoint_method": "POST",
    "endpoint_uri": "/OrderService/CreateOrder",
    "endpoint_description": "SOAP CreateOrder operation"
  }'

Step 3: Add XML Validation (Optional)

curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/endpoint/endpoint/validation" -d '{
    "endpoint_id": "<endpoint_id>",
    "validation_enabled": true,
    "validation_schema": {
      "validation_schema": {
        "orderId": {"required": true, "type": "string"},
        "customerId": {"required": true, "type": "string"}
      }
    }
  }'

Step 4: Call SOAP Gateway

curl -s -b "$COOKIE" \
  -H 'Content-Type: text/xml' \
  -H 'SOAPAction: CreateOrder' \
  -d '<soap:Envelope>...</soap:Envelope>' \
  "$BASE/api/soap/legacy-orders/v1/OrderService/CreateOrder"

Monitoring and Health Checks

Health Endpoints

# Liveness probe (basic health)
curl -s "$BASE/platform/monitor/liveness"
# Returns: {"status": "alive"}

# Readiness probe (checks Redis/MongoDB)
curl -s "$BASE/platform/monitor/readiness"
# Returns: {"status": "ready", "mongodb": "connected", "redis": "connected"}

# Gateway status (public endpoint)
curl -s "$BASE/api/health"
# Returns: {"status": "ok", "uptime": 12345, "memory": {...}}

Metrics

# Requires authentication + manage_gateway permission
curl -s -b "$COOKIE" "$BASE/platform/monitor/metrics?range=24h"

Metrics include:

  • Request counts per API
  • Average response times
  • Error rates
  • Credit usage
  • Rate limit hits

Logs

Via UI: Navigate to Logging section

Via API:

# View logs (requires view_logs permission)
curl -s -b "$COOKIE" "$BASE/platform/logging/logs?limit=100"

# Export logs (requires export_logs permission)
curl -s -b "$COOKIE" "$BASE/platform/logging/export?start_date=2024-01-01"

Log files:

  • backend-services/logs/doorman.log - Main application log
  • backend-services/logs/doorman-trail.log - Audit trail

Common Errors and Troubleshooting

GTW001: API Not Found

Error message: "API not found"

Causes:

  • API with that name/version doesn't exist
  • Typo in api_name or api_version

Solutions:

# List all APIs
curl -s -b "$COOKIE" "$BASE/platform/api"

# Check API details
curl -s -b "$COOKIE" "$BASE/platform/api/customers/v1"

GTW002: No Endpoints Defined

Error message: "No endpoints defined for this API"

Causes:

  • API created but no endpoints added

Solutions:

# Add at least one endpoint
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/endpoint" -d '{
    "api_name": "customers",
    "api_version": "v1",
    "endpoint_method": "GET",
    "endpoint_uri": "/health"
  }'

GTW003: Endpoint Not Found

Error message: "Endpoint not found: GET /users"

Causes:

  • Method/URI combination not added as an endpoint
  • Typo in path or method

Solutions:

# List endpoints for API
curl -s -b "$COOKIE" "$BASE/platform/endpoint?api_name=customers&api_version=v1"

# Check URI matches exactly (including leading slash)
# Gateway path: /api/rest/customers/v1/users
# Endpoint URI should be: /users

GTW008: No Credits/Tokens

Error message: "No credits available"

Causes:

  • User ran out of credits
  • No token group assigned
  • Credits not enabled for API

Solutions:

# Check user's credits
curl -s -b "$COOKIE" "$BASE/platform/credit/{username}"

# Add more credits
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/credit/{username}" -d '{
    "api_credit_group": "demo-api",
    "credit_tiers": [{"tier_name": "default", "credits": 100000, ...}]
  }'

HTTP 403: Permission Denied

Error message: "You do not have permission..."

Causes:

  • User lacks required role permission
  • User not in allowed group for API
  • User not subscribed to API

Solutions:

# Check user's roles
curl -s -b "$COOKIE" "$BASE/platform/user/{username}"

# Add required role
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/user/{username}/roles" -d '{
    "roles": ["manage_apis"]
  }'

# Subscribe to API
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/subscription/subscribe" -d '{
    "username": "alice",
    "api_name": "customers",
    "api_version": "v1"
  }'

CORS Errors

Error: "CORS policy: No 'Access-Control-Allow-Origin' header"

Causes:

  • Client origin not in ALLOWED_ORIGINS
  • Wildcard origin with credentials enabled

Solutions:

# Update environment variable
ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
CORS_STRICT=true

# Use CORS checker tool
curl -s -b "$COOKIE" -H 'Content-Type: application/json' -X POST \
  "$BASE/platform/tools/cors/check" -d '{
    "origin": "https://app.example.com",
    "method": "GET",
    "with_credentials": true
  }'

CSRF Errors

Error: "Invalid CSRF token"

Causes:

  • X-CSRF-Token header missing
  • CSRF token doesn't match cookie
  • HTTPS not properly configured

Solutions:

# Ensure HTTPS is enabled
HTTPS_ONLY=true

# Include CSRF token in request
curl -s -b "$COOKIE" \
  -H "X-CSRF-Token: $(grep csrf_token cookies.txt | awk '{print $7}')" \
  -H 'Content-Type: application/json' \
  -X POST "$BASE/platform/api" -d '{...}'

Request Too Large (413)

Error code: REQ001

Causes:

  • Request body exceeds MAX_BODY_SIZE_BYTES

Solutions:

# Increase limit for specific API type
MAX_BODY_SIZE_BYTES_SOAP=2097152  # 2MB for SOAP
MAX_BODY_SIZE_BYTES_REST=524288   # 512KB for REST

# Or increase global limit
MAX_BODY_SIZE_BYTES=2097152

Tips and Best Practices

API Configuration

  • Restrict headers: Only allow headers that upstream needs via api_allowed_headers
  • Use retries wisely: Set api_allowed_retry_count based on upstream idempotency
  • Enable validation: Validate requests at the gateway to protect upstream services
  • Version APIs: Always use explicit versions (v1, v2, etc.)

Routing

  • Client routing: Use client-key header for blue/green deployments or premium tiers
  • Server pools: Provide multiple servers in api_servers for load balancing
  • Precedence: Remember routing > endpoint > API server selection

Security

  • Subscribe users: Always require subscriptions to control access
  • Use groups: Organize users into groups for easier access management
  • Enable credits: Track and limit usage with credit system
  • Validate inputs: Add endpoint validation to reject malformed requests early

Monitoring

  • Enable JSON logs: Set LOG_FORMAT=json in production
  • Ship to SIEM: Forward logs to centralized log management
  • Monitor metrics: Regularly review /platform/monitor/metrics
  • Set up alerts: Alert on error rates, credit exhaustion, rate limit hits

Performance

  • Use Redis: Enable Redis for distributed rate limiting and caching
  • Connection pooling: Upstream servers are pooled automatically
  • Limit body sizes: Set appropriate MAX_BODY_SIZE_BYTES per API type
  • Enable compression: Configure upstream responses with compression

Next Steps