Skip to content

Latest commit

 

History

History
2126 lines (1722 loc) · 50.6 KB

File metadata and controls

2126 lines (1722 loc) · 50.6 KB

Admin API Management - Complete Testing Guide

Table of Contents


Overview

This guide provides comprehensive documentation for testing the Admin API Management endpoints. The API allows you to dynamically register, configure, and manage APIs with rate limiting, routing, and reverse proxy capabilities.

Key Features:

  • Reverse proxy with upstream URL configuration
  • Sliding window rate limiting (always enabled)
  • Bearer token authentication for admin endpoints
  • Bot detection and IP blocking
  • Real-time metrics and event streaming
  • Strict HTTP method validation
  • No path stripping (full paths forwarded to upstream)

Base Configuration

Base URL

http://localhost:8080

Common Headers

Content-Type: application/json
Authorization: Bearer YOUR_ADMIN_TOKEN

Response Codes

Code Description
200 OK Successful GET/PUT request
201 Created Successful POST request
204 No Content Successful DELETE request
400 Bad Request Invalid request body or parameters
401 Unauthorized Missing or invalid admin token
404 Not Found Resource not found
405 Method Not Allowed HTTP method doesn't match endpoint
409 Conflict Resource already exists
500 Internal Server Error Server error

API Endpoints

1. Create API

Endpoint: POST /admin/apis

Creates a new API registration with routing, rate limiting, and upstream configuration.

Request Body

{
  "id": "user-service",
  "service_id": "user-service-v1",
  "name": "User Service API",
  "description": "Handles user operations",
  "upstream_url": "http://user-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000
  },
  "endpoints": [
    {
      "id": "get-users",
      "path": "/api/users",
      "method": "GET",
      "limits": {
        "requests_per_second": 50,
        "burst_size": 100,
        "block_duration": 300000000000
      },
      "priority": 10
    },
    {
      "id": "create-user",
      "path": "/api/users",
      "method": "POST",
      "limits": {
        "requests_per_second": 20,
        "burst_size": 40,
        "block_duration": 600000000000
      },
      "priority": 20
    },
    {
      "id": "get-user",
      "path": "/api/users/{id}",
      "method": "GET",
      "limits": {
        "requests_per_second": 60,
        "burst_size": 120
      },
      "priority": 15
    }
  ]
}

Field Details:

Field Type Required Default Description
id string Yes - Unique API identifier
service_id string Yes - Service grouping identifier
name string No - Human-readable name
description string No - API description
upstream_url string Yes - Backend server URL
status string No "active" active, maintenance, deprecated, disabled
default_limits object No - Default rate limits for all endpoints
endpoints array Yes - Endpoint definitions (at least one required)

Rate Limits Object:

Field Type Required Default Description
requests_per_second number Yes - Maximum requests per second
burst_size number Yes - Burst capacity
block_duration number (nanoseconds) No 300000000000 Block duration (default: 5 minutes)
use_sliding_window boolean Auto true Always true (enforced by system)

Endpoint Object:

Field Type Required Default Description
id string Yes - Unique endpoint identifier within API
path string Yes - Full URL path (e.g., /api/users)
method string Yes - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
limits object No API defaults Endpoint-specific rate limits
priority number No 100 Matching priority (lower = higher priority)
enabled boolean Auto true Always true (enforced by system)

Important Notes:

  • No base_path required - paths are used as-is
  • Full paths required - use /api/users, not /users
  • Methods validated - must be valid HTTP methods, auto-uppercase
  • At least one endpoint required - empty endpoints array rejected
  • No auth_type field - authentication handled at middleware layer, not per-endpoint

Response (201 Created)

{
  "id": "user-service",
  "service_id": "user-service-v1",
  "name": "User Service API",
  "description": "Handles user operations",
  "upstream_url": "http://user-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "endpoints": [
    {
      "id": "get-users",
      "path": "/api/users",
      "method": "GET",
      "limits": {
        "requests_per_second": 50,
        "burst_size": 100,
        "block_duration": 300000000000,
        "use_sliding_window": true
      },
      "priority": 10,
      "enabled": true
    },
    {
      "id": "create-user",
      "path": "/api/users",
      "method": "POST",
      "limits": {
        "requests_per_second": 20,
        "burst_size": 40,
        "block_duration": 600000000000,
        "use_sliding_window": true
      },
      "priority": 20,
      "enabled": true
    }
  ],
  "created_at": "2026-03-10T10:00:00.000000000+05:00",
  "updated_at": "2026-03-10T10:00:00.000000000+05:00"
}

cURL Examples

Create Full API:

curl -X POST http://localhost:8080/admin/apis \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "id": "order-service",
    "service_id": "commerce-v1",
    "name": "Order Service",
    "description": "Handles order processing",
    "upstream_url": "http://order-backend:8080",
    "status": "active",
    "default_limits": {
      "requests_per_second": 100,
      "burst_size": 200,
      "block_duration": 300000000000
    },
    "endpoints": [
      {
        "id": "list-orders",
        "path": "/api/orders",
        "method": "GET",
        "limits": {
          "requests_per_second": 50,
          "burst_size": 100
        },
        "priority": 10
      },
      {
        "id": "create-order",
        "path": "/api/orders",
        "method": "POST",
        "limits": {
          "requests_per_second": 20,
          "burst_size": 40,
          "block_duration": 600000000000
        },
        "priority": 20
      }
    ]
  }'

Create Minimal API (Required Fields Only):

curl -X POST http://localhost:8080/admin/apis \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "id": "minimal-api",
    "service_id": "minimal-service",
    "upstream_url": "http://minimal-backend:8080",
    "endpoints": [
      {
        "id": "health",
        "path": "/health",
        "method": "GET"
      }
    ]
  }'

2. Update API

Endpoint: PUT /admin/apis/{apiID}

Updates an existing API. Supports partial updates - only send fields you want to change.

Request Body - Full Update

{
  "name": "Updated Order Service",
  "description": "Updated description for order processing",
  "upstream_url": "http://new-order-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 150,
    "burst_size": 300,
    "block_duration": 300000000000
  }
}

Request Body - Partial Updates

Update Name Only:

{
  "name": "Updated API Name"
}

Update Rate Limits Only:

{
  "default_limits": {
    "requests_per_second": 200,
    "burst_size": 400,
    "block_duration": 300000000000
  }
}

Update Status to Maintenance:

{
  "status": "maintenance"
}

Update Upstream URL:

{
  "upstream_url": "http://new-backend:9000"
}

Response (200 OK)

Returns the complete updated API object.

{
  "id": "order-service",
  "service_id": "commerce-v1",
  "name": "Updated Order Service",
  "description": "Updated description for order processing",
  "upstream_url": "http://new-order-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 150,
    "burst_size": 300,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "endpoints": [...],
  "created_at": "2026-03-10T10:00:00.000000000+05:00",
  "updated_at": "2026-03-10T10:30:00.000000000+05:00"
}

cURL Examples

# Full update
curl -X PUT http://localhost:8080/admin/apis/order-service \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "name": "Updated Order Service",
    "upstream_url": "http://new-backend:9000",
    "default_limits": {
      "requests_per_second": 150,
      "burst_size": 300
    }
  }'

# Partial update - status only
curl -X PUT http://localhost:8080/admin/apis/order-service \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{"status": "maintenance"}'

3. Get API

Endpoint: GET /admin/apis/{apiID}

Retrieves a single API by ID.

Response (200 OK)

{
  "id": "order-service",
  "service_id": "commerce-v1",
  "name": "Order Service",
  "description": "Handles order processing",
  "upstream_url": "http://order-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "endpoints": [
    {
      "id": "list-orders",
      "path": "/api/orders",
      "method": "GET",
      "limits": {
        "requests_per_second": 50,
        "burst_size": 100,
        "block_duration": 300000000000,
        "use_sliding_window": true
      },
      "priority": 10,
      "enabled": true
    }
  ],
  "created_at": "2026-03-10T10:00:00.000000000+05:00",
  "updated_at": "2026-03-10T10:00:00.000000000+05:00"
}

cURL Example

curl http://localhost:8080/admin/apis/order-service \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

4. List APIs

Endpoint: GET /admin/apis

Lists all registered APIs with optional filtering and pagination.

Query Parameters

Parameter Type Description Example
service_id string Filter by service ID commerce-v1
status string Filter by status active, maintenance
search string Search in name/description order
limit integer Limit results 10
offset integer Pagination offset 0

Response (200 OK)

{
  "apis": [
    {
      "id": "order-service",
      "service_id": "commerce-v1",
      "name": "Order Service",
      "description": "Handles order processing",
      "upstream_url": "http://order-backend:8080",
      "status": "active",
      "created_at": "2026-03-10T10:00:00.000000000+05:00",
      "updated_at": "2026-03-10T10:00:00.000000000+05:00"
    },
    {
      "id": "user-service",
      "service_id": "user-service-v1",
      "name": "User Service API",
      "upstream_url": "http://user-backend:8080",
      "status": "active",
      "created_at": "2026-03-10T10:30:00.000000000+05:00",
      "updated_at": "2026-03-10T10:30:00.000000000+05:00"
    }
  ],
  "count": 2
}

cURL Examples

# List all APIs
curl http://localhost:8080/admin/apis \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Filter by status
curl "http://localhost:8080/admin/apis?status=active" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Filter by service_id with pagination
curl "http://localhost:8080/admin/apis?service_id=commerce-v1&limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

5. Delete API

Endpoint: DELETE /admin/apis/{apiID}

Deletes an API and all its endpoints.

Response

204 No Content - No response body

cURL Example

curl -X DELETE http://localhost:8080/admin/apis/order-service \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

6. List Endpoints

Endpoint: GET /admin/apis/{apiID}/endpoints

Lists all endpoints for a specific API.

Response (200 OK)

{
  "endpoints": [
    {
      "id": "list-orders",
      "path": "/api/orders",
      "method": "GET",
      "limits": {
        "requests_per_second": 50,
        "burst_size": 100,
        "block_duration": 300000000000,
        "use_sliding_window": true
      },
      "priority": 10,
      "enabled": true
    },
    {
      "id": "create-order",
      "path": "/api/orders",
      "method": "POST",
      "limits": {
        "requests_per_second": 20,
        "burst_size": 40,
        "block_duration": 600000000000,
        "use_sliding_window": true
      },
      "priority": 20,
      "enabled": true
    }
  ],
  "count": 2
}

cURL Example

curl http://localhost:8080/admin/apis/order-service/endpoints \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

7. Add Endpoint

Endpoint: POST /admin/apis/{apiID}/endpoints

Adds a new endpoint to an existing API.

Request Body

{
  "id": "update-order",
  "path": "/api/orders/{id}",
  "method": "PUT",
  "limits": {
    "requests_per_second": 15,
    "burst_size": 30,
    "block_duration": 300000000000
  },
  "priority": 25
}

Field Details:

Field Type Required Default Description
id string Yes - Unique endpoint identifier within API
path string Yes - Full URL path (e.g., /api/orders/{id})
method string Yes - HTTP method (auto-uppercase)
limits object No API defaults Endpoint-specific rate limits
priority number No 100 Matching priority

Response (201 Created)

{
  "id": "update-order",
  "path": "/api/orders/{id}",
  "method": "PUT",
  "limits": {
    "requests_per_second": 15,
    "burst_size": 30,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "priority": 25,
  "enabled": true
}

cURL Example

curl -X POST http://localhost:8080/admin/apis/order-service/endpoints \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "id": "update-order",
    "path": "/api/orders/{id}",
    "method": "PUT",
    "limits": {
      "requests_per_second": 15,
      "burst_size": 30
    },
    "priority": 25
  }'

8. Get Endpoint

Endpoint: GET /admin/apis/{apiID}/endpoints/{endpointID}

Retrieves a specific endpoint.

Response (200 OK)

{
  "id": "list-orders",
  "path": "/api/orders",
  "method": "GET",
  "limits": {
    "requests_per_second": 50,
    "burst_size": 100,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "priority": 10,
  "enabled": true
}

cURL Example

curl http://localhost:8080/admin/apis/order-service/endpoints/list-orders \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

9. Update Endpoint

Endpoint: PUT /admin/apis/{apiID}/endpoints/{endpointID}

Updates an existing endpoint. Supports partial updates.

Request Body - Full Update

{
  "path": "/api/orders/v2/{id}",
  "method": "PATCH",
  "limits": {
    "requests_per_second": 25,
    "burst_size": 50,
    "block_duration": 300000000000
  },
  "priority": 15
}

Request Body - Partial Update

Update Limits Only:

{
  "limits": {
    "requests_per_second": 100,
    "burst_size": 200
  }
}

Update Priority Only:

{
  "priority": 5
}

Response (200 OK)

{
  "id": "list-orders",
  "path": "/api/orders",
  "method": "GET",
  "limits": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "priority": 5,
  "enabled": true
}

cURL Examples

# Update limits
curl -X PUT http://localhost:8080/admin/apis/order-service/endpoints/list-orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "limits": {
      "requests_per_second": 100,
      "burst_size": 200
    }
  }'

# Update priority
curl -X PUT http://localhost:8080/admin/apis/order-service/endpoints/list-orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{"priority": 5}'

10. Delete Endpoint

Endpoint: DELETE /admin/apis/{apiID}/endpoints/{endpointID}

Deletes a specific endpoint.

Response

204 No Content - No response body

cURL Example

curl -X DELETE http://localhost:8080/admin/apis/order-service/endpoints/update-order \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

11. Bulk Import

Endpoint: POST /admin/apis/import

Imports multiple APIs at once.

Request Body

{
  "apis": [
    {
      "id": "bulk-api-1",
      "service_id": "bulk-service",
      "name": "Bulk API 1",
      "upstream_url": "http://localhost:8082",
      "default_limits": {
        "requests_per_second": 50,
        "burst_size": 100,
        "block_duration": 300000000000
      },
      "endpoints": [
        {
          "id": "get-data",
          "path": "/api/data",
          "method": "GET",
          "limits": {
            "requests_per_second": 50,
            "burst_size": 100
          },
          "priority": 10
        }
      ]
    },
    {
      "id": "bulk-api-2",
      "service_id": "bulk-service",
      "name": "Bulk API 2",
      "upstream_url": "http://localhost:8083",
      "default_limits": {
        "requests_per_second": 30,
        "burst_size": 60,
        "block_duration": 300000000000
      },
      "endpoints": [
        {
          "id": "health",
          "path": "/health",
          "method": "GET",
          "priority": 1
        }
      ]
    }
  ],
  "overwrite_existing": false
}

Response (200 OK)

{
  "imported": 2,
  "updated": 0,
  "failed": 0,
  "errors": []
}

With Errors:

{
  "imported": 1,
  "updated": 0,
  "failed": 1,
  "errors": [
    "Failed to register bulk-api-2: API with ID bulk-api-2 already exists"
  ]
}

cURL Example

curl -X POST http://localhost:8080/admin/apis/import \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "apis": [
      {
        "id": "imported-api",
        "service_id": "imported-service",
        "name": "Imported API",
        "upstream_url": "http://imported-backend:8080",
        "default_limits": {
          "requests_per_second": 100,
          "burst_size": 200
        },
        "endpoints": [
          {
            "id": "health",
            "path": "/health",
            "method": "GET",
            "priority": 1
          }
        ]
      }
    ],
    "overwrite_existing": false
  }'

12. Export All

Endpoint: GET /admin/apis/export

Exports all APIs in JSON format for backup or migration.

Response (200 OK)

{
  "exported_at": "2026-03-10T10:30:00Z",
  "count": 2,
  "apis": [
    {
      "id": "order-service",
      "service_id": "commerce-v1",
      "name": "Order Service",
      "upstream_url": "http://order-backend:8080",
      "status": "active",
      "default_limits": {
        "requests_per_second": 100,
        "burst_size": 200,
        "block_duration": 300000000000,
        "use_sliding_window": true
      },
      "endpoints": [
        {
          "id": "list-orders",
          "path": "/api/orders",
          "method": "GET",
          "limits": {
            "requests_per_second": 50,
            "burst_size": 100,
            "block_duration": 300000000000,
            "use_sliding_window": true
          },
          "priority": 10,
          "enabled": true
        }
      ],
      "created_at": "2026-03-10T10:00:00.000000000+05:00",
      "updated_at": "2026-03-10T10:00:00.000000000+05:00"
    }
  ]
}

cURL Example

# Export to file
curl http://localhost:8080/admin/apis/export \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  > apis-backup-$(date +%Y%m%d).json

13. List Templates

Endpoint: GET /admin/apis/templates

Lists available service templates with predefined rate limits.

Response (200 OK)

{
  "templates": {
    "standard": {
      "requests_per_second": 100,
      "burst_size": 200,
      "window_size": 60000000000,
      "block_duration": 300000000000
    },
    "premium": {
      "requests_per_second": 500,
      "burst_size": 1000,
      "window_size": 60000000000,
      "block_duration": 300000000000
    },
    "public": {
      "requests_per_second": 1000,
      "burst_size": 2000,
      "window_size": 10000000000,
      "block_duration": 60000000000
    },
    "secure": {
      "requests_per_second": 10,
      "burst_size": 15,
      "window_size": 60000000000,
      "block_duration": 900000000000
    }
  },
  "count": 4
}

cURL Example

curl http://localhost:8080/admin/apis/templates \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

14. Create from Template

Endpoint: POST /admin/apis/from-template

Creates an API from a predefined template with automatic rate limit defaults.

Request Body

{
  "api_id": "premium-api",
  "service_id": "premium-service",
  "name": "Premium API from Template",
  "upstream_url": "http://premium-backend:8080",
  "template": "premium",
  "endpoints": [
    {
      "id": "get-data",
      "path": "/api/data",
      "method": "GET",
      "priority": 10
    },
    {
      "id": "post-data",
      "path": "/api/data",
      "method": "POST",
      "priority": 20
    }
  ]
}

Template Values Applied:

  • standard: 100 RPS, 200 burst, 5min block
  • premium: 500 RPS, 1000 burst, 5min block
  • public: 1000 RPS, 2000 burst, 1min block
  • secure: 10 RPS, 15 burst, 15min block

Response (201 Created)

{
  "id": "premium-api",
  "service_id": "premium-service",
  "name": "Premium API from Template",
  "upstream_url": "http://premium-backend:8080",
  "status": "active",
  "default_limits": {
    "requests_per_second": 500,
    "burst_size": 1000,
    "window_size": 60000000000,
    "block_duration": 300000000000,
    "use_sliding_window": true
  },
  "endpoints": [
    {
      "id": "get-data",
      "path": "/api/data",
      "method": "GET",
      "limits": {
        "requests_per_second": 500,
        "burst_size": 1000,
        "window_size": 60000000000,
        "block_duration": 300000000000,
        "use_sliding_window": true
      },
      "priority": 10,
      "enabled": true
    }
  ],
  "created_at": "2026-03-10T10:00:00.000000000+05:00",
  "updated_at": "2026-03-10T10:00:00.000000000+05:00"
}

cURL Example

curl -X POST http://localhost:8080/admin/apis/from-template \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "api_id": "my-premium-api",
    "service_id": "my-service",
    "name": "My Premium API",
    "upstream_url": "http://backend:8080",
    "template": "premium",
    "endpoints": [
      {
        "id": "health",
        "path": "/health",
        "method": "GET",
        "priority": 1
      }
    ]
  }'

15. Test Rule

Endpoint: POST /admin/apis/test

Tests a rate limit rule against a path without applying it.

Request Body

{
  "path": "/api/orders/orders",
  "method": "GET",
  "rule": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000
  }
}

Response (200 OK)

{
  "path": "/api/orders/orders",
  "method": "GET",
  "matched_rule": {
    "api_id": "order-service",
    "endpoint_id": "list-orders",
    "service_id": "commerce-v1",
    "path": "/api/orders/orders",
    "method": "GET",
    "requests_per_second": 50,
    "burst_size": 100,
    "window_size": 60000000000,
    "block_duration": 300000000000,
    "use_sliding_window": true,
    "priority": 10,
    "enabled": true,
    "upstream_url": "http://order-backend:8080",
    "is_excluded": false
  },
  "would_apply": true,
  "test_limits": {
    "requests_per_second": 100,
    "burst_size": 200,
    "block_duration": 300000000000
  }
}

cURL Example

curl -X POST http://localhost:8080/admin/apis/test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -d '{
    "path": "/api/orders/orders",
    "method": "GET",
    "rule": {
      "requests_per_second": 100,
      "burst_size": 200
    }
  }'

16. Resolve Path

Endpoint: GET /admin/apis/resolve

Shows which rule would apply to a specific path.

Query Parameters

Parameter Type Required Description
path string Yes Path to resolve

Response (200 OK)

{
  "path": "/api/orders/orders",
  "resolved_rule": {
    "api_id": "order-service",
    "endpoint_id": "list-orders",
    "service_id": "commerce-v1",
    "path": "/api/orders/orders",
    "method": "GET",
    "requests_per_second": 50,
    "burst_size": 100,
    "window_size": 60000000000,
    "block_duration": 300000000000,
    "use_sliding_window": true,
    "priority": 10,
    "enabled": true,
    "upstream_url": "http://order-backend:8080"
  },
  "excluded": false
}

cURL Example

curl "http://localhost:8080/admin/apis/resolve?path=/api/orders/orders" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

17. Reload Rules

Endpoint: POST /admin/apis/reload

Triggers a reload of all rate limiting rules from the registry file.

Response (200 OK)

{
  "status": "reloaded",
  "message": "Rules reloaded successfully"
}

cURL Example

curl -X POST http://localhost:8080/admin/apis/reload \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

18. Subscribe to Events

Endpoint: GET /admin/apis/events

Subscribes to Server-Sent Events (SSE) for real-time API changes.

Response (Server-Sent Events Stream)

data: {"type": "connected", "timestamp": "2026-03-10T10:00:00Z"}

data: {"type": "api_created", "api_id": "new-api", "timestamp": "2026-03-10T10:05:00Z", "data": {"id": "new-api", ...}}

data: {"type": "api_updated", "api_id": "order-service", "timestamp": "2026-03-10T10:10:00Z"}

data: {"type": "api_deleted", "api_id": "old-api", "timestamp": "2026-03-10T10:15:00Z"}

cURL Example

# Stream events (requires -N for no buffering)
curl -N http://localhost:8080/admin/apis/events \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

19. Rate Limit Check Endpoint

The /check endpoint provides a dry-run rate limiting check that allows you to test whether a specific request would be allowed, blocked, or rate-limited without actually consuming quota or forwarding the request to the backend. This is useful for pre-flight checks, client-side rate limit awareness, and debugging.

19.1 Check Rate Limit (Dry Run)

Endpoint: POST /check

Tests a hypothetical request against the rate limiting rules and returns the decision without incrementing counters or blocking the client.

Request Body

{
  "service_id": "user-service",
  "endpoint": "/api/users",
  "ip": "192.168.1.100",
  "user_id": "user_12345",
  "headers": {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept": "application/json"
  }
}

Field Details:

Field Type Required Description
service_id string Yes The service identifier to check against
endpoint string Yes The full path of the endpoint to test
ip string Yes Client IP address (IPv4 or IPv6)
user_id string No User identifier for user-based limiting (if provided, takes precedence over IP)
headers object No HTTP headers for bot detection analysis

Response (200 OK) - Allowed

{
  "allowed": true,
  "reason": "allowed",
  "service_id": "user-service",
  "endpoint": "/api/users",
  "client_id": "user_12345",
  "limit_type": "user_based",
  "remaining": 49,
  "reset_at": "2026-03-10T10:05:00Z",
  "rule": {
    "requests_per_second": 50,
    "burst_size": 100,
    "block_duration": 300000000000
  }
}

Response (200 OK) - Blocked/Bot Detected

{
  "allowed": false,
  "reason": "bot_detected",
  "service_id": "user-service",
  "endpoint": "/api/users",
  "client_id": "192.168.1.200",
  "limit_type": "ip_based",
  "details": "Missing or suspicious User-Agent header"
}

Response (200 OK) - Rate Limit Exceeded

{
  "allowed": false,
  "reason": "rate_limit_exceeded",
  "service_id": "user-service",
  "endpoint": "/api/users",
  "client_id": "192.168.1.50",
  "limit_type": "ip_based",
  "retry_after": 45,
  "details": "Rate limit exceeded. Try again in 45 seconds."
}

Response (200 OK) - Excluded Path

{
  "allowed": true,
  "reason": "excluded_path",
  "service_id": "user-service",
  "endpoint": "/health",
  "details": "Path is excluded from rate limiting"
}

Response (400 Bad Request) - Missing Required Fields

{
  "error": "missing_required_fields",
  "message": "service_id, endpoint, and ip are required"
}

Response (400 Bad Request) - Invalid JSON

{
  "error": "invalid_json",
  "message": "Request body contains malformed JSON"
}

Response (401 Unauthorized) - Missing API Key

{
  "error": "unauthorized",
  "message": "X-API-Key header is required"
}

cURL Examples

Basic Check (Allowed):

curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "service_id": "user-service",
    "endpoint": "/api/users",
    "ip": "192.168.1.100",
    "headers": {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      "Accept": "application/json"
    }
  }'

Check with User ID (User-Based Limiting):

curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "service_id": "order-service",
    "endpoint": "/api/orders",
    "ip": "192.168.1.101",
    "user_id": "user_12345",
    "headers": {
      "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
      "Accept": "application/json"
    }
  }'

Bot Detection Test (Should Return Blocked):

curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "service_id": "user-service",
    "endpoint": "/api/users",
    "ip": "192.168.1.200",
    "headers": {
      "User-Agent": "curl/7.68.0",
      "Accept": "*/*"
    }
  }'

IPv6 Address Check:

curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "service_id": "order-service",
    "endpoint": "/api/orders",
    "ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
    "headers": {
      "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
      "Accept": "application/json"
    }
  }'

Excluded Path Check (Health Check):

curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "service_id": "user-service",
    "endpoint": "/health",
    "ip": "192.168.1.102",
    "headers": {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
      "Accept": "application/json"
    }
  }'

19.2 Check Response Fields Reference

Field Type Description
allowed boolean Whether the request would be allowed
reason string Decision reason: allowed, rate_limit_exceeded, bot_detected, blocked_ip, excluded_path, service_not_found, endpoint_not_found
service_id string The service that was checked
endpoint string The endpoint path that was checked
client_id string The identifier used for limiting (IP or user_id)
limit_type string ip_based, user_based, or none
remaining number Remaining requests in current window (if applicable)
reset_at string ISO 8601 timestamp when the limit resets (if applicable)
retry_after number Seconds until retry is allowed (if rate limited)
rule object The rate limit rule that was applied
details string Human-readable explanation of the decision

19.3 Bot Detection Behavior

The /check endpoint includes bot detection that analyzes the User-Agent header and other request characteristics:

Scenario Result Reason
Missing User-Agent Blocked bot_detected
Empty User-Agent Blocked bot_detected
Known bot signatures (curl, wget, python-requests, etc.) Blocked bot_detected
Suspicious patterns Blocked bot_detected
Valid browser User-Agent Allowed allowed

19.4 Rate Limiting Behavior

The check endpoint evaluates limits in this priority order:

  1. Excluded Paths: If the path matches an exclusion list (e.g., /health), returns allowed immediately
  2. Bot Detection: If bot detected, returns blocked immediately
  3. Blocked IPs: If IP is in blocklist, returns blocked with remaining block time
  4. User-Based Limiting: If user_id provided, check against user limits
  5. IP-Based Limiting: If no user_id, check against IP limits (with subnet normalization)

Important Notes:

  • The /check endpoint is a dry-run - it does not consume quota or increment counters
  • It returns the current state of limits without modifying them
  • Use this for pre-flight checks before making actual requests
  • The endpoint requires X-API-Key authentication (different from admin endpoints that use Bearer tokens)

19.5 Testing Rate Limits with Check Endpoint

Since /check doesn't consume quota, you can use it to safely test your rate limiting configuration:

# Test 1: Verify normal request is allowed
curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: test-key" \
  -d '{"service_id":"payment-service","endpoint":"/api/v1/payments","ip":"192.168.1.1","headers":{"User-Agent":"Mozilla/5.0"}}'

# Test 2: Verify bot is detected
curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: test-key" \
  -d '{"service_id":"payment-service","endpoint":"/api/v1/payments","ip":"192.168.1.1","headers":{"User-Agent":"curl/7.68.0"}}'

# Test 3: Verify excluded path
curl -X POST http://localhost:8080/check \
  -H "Content-Type: application/json" \
  -H "X-API-Key: test-key" \
  -d '{"service_id":"payment-service","endpoint":"/health","ip":"192.168.1.1","headers":{"User-Agent":"Mozilla/5.0"}}'

Additional System Endpoints

Where to insert: Place this entire block immediately before the "Additional System Endpoints" section (which starts with ### Health Check). The --- horizontal rule at the beginning creates proper separation from the previous Metrics API section.

Also, update your Table of Contents at the top of the README to include:


Metrics API

The Metrics API provides real-time and historical metrics for monitoring API usage and performance.

Base URL

http://localhost:8080/admin/metrics

Endpoints

1. List All APIs with Metrics

Endpoint: GET /admin/metrics

Returns all APIs with their current metrics summary.

Response (200 OK)

{
  "apis": [
    {
      "id": "order-service",
      "total_requests": 1500,
      "allowed_requests": 1450,
      "blocked_requests": 50,
      "rate_limited_requests": 30,
      "avg_response_time_ms": 45.5,
      "status_codes": {
        "200": 1400,
        "201": 50,
        "429": 30,
        "500": 20
      }
    }
  ],
  "count": 1,
  "generated_at": "2026-03-10T10:00:00Z"
}

cURL Example

curl http://localhost:8080/admin/metrics \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

2. Get API Metrics (Time Range)

Endpoint: GET /admin/metrics/{apiID}

Query parameters for time range:

  • from - Start time (RFC3339)
  • to - End time (RFC3339)
  • range - Relative range: 1h, 6h, 12h, 24h, 3d, 7d, 30d, 90d, 1y

Predefined Time Ranges

Endpoint Description
GET /admin/metrics/{apiID}/current Current hour
GET /admin/metrics/{apiID}/today Today (00:00 to now)
GET /admin/metrics/{apiID}/yesterday Yesterday full day
GET /admin/metrics/{apiID}/week Last 7 days
GET /admin/metrics/{apiID}/month Last 30 days
GET /admin/metrics/{apiID}/year Last 365 days

Custom Range

Endpoint: GET /admin/metrics/{apiID}/range

Query parameters:

  • days - Number of days back
  • hours - Number of hours back

Response (200 OK)

{
  "api_id": "order-service",
  "query_range": "last_7_days",
  "from": "2026-03-03T10:00:00Z",
  "to": "2026-03-10T10:00:00Z",
  "total_requests": 10500,
  "allowed_requests": 10000,
  "blocked_requests": 300,
  "rate_limited_requests": 200,
  "avg_response_time_ms": 42.3,
  "requests_per_hour": [
    {"hour": "2026-03-03T10:00:00Z", "count": 150},
    {"hour": "2026-03-03T11:00:00Z", "count": 180}
  ],
  "top_ips": [
    {"ip": "192.168.1.1", "requests": 500},
    {"ip": "192.168.1.2", "requests": 300}
  ],
  "status_codes": {
    "200": 9500,
    "201": 500,
    "429": 200,
    "500": 100
  },
  "endpoints": [
    {
      "endpoint_id": "list-orders",
      "path": "/api/orders",
      "method": "GET",
      "requests": 8000,
      "avg_response_time_ms": 35.0
    }
  ]
}

cURL Examples

# Last 24 hours (default)
curl http://localhost:8080/admin/metrics/order-service \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Today only
curl http://localhost:8080/admin/metrics/order-service/today \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Last 7 days
curl http://localhost:8080/admin/metrics/order-service/week \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Custom range - last 3 days
curl http://localhost:8080/admin/metrics/order-service/range?days=3 \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Custom range - last 6 hours
curl http://localhost:8080/admin/metrics/order-service/range?hours=6 \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Specific date range
curl "http://localhost:8080/admin/metrics/order-service?from=2026-03-01T00:00:00Z&to=2026-03-10T00:00:00Z" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

3. Stream Real-Time Metrics

Endpoint: GET /admin/metrics/{apiID}/stream

Server-Sent Events stream with real-time metrics updates every 5 seconds.

Response (SSE Stream)

data: {"type": "connected", "timestamp": "2026-03-10T10:00:00Z", "metrics": {...}}

data: {"type": "update", "timestamp": "2026-03-10T10:00:05Z", "metrics": {...}}

cURL Example

curl -N http://localhost:8080/admin/metrics/order-service/stream \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

4. Export Metrics

Endpoint: GET /admin/metrics/{apiID}/export

Exports raw metrics data as JSON file.

Query parameters:

  • format - Export format (default: json)

Response

File download with Content-Disposition: attachment

cURL Example

curl http://localhost:8080/admin/metrics/order-service/export \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  > order-service-metrics.json

Configuration Reference

API Object Structure

Field Type Required Default Description
id string Yes - Unique API identifier
service_id string Yes - Service grouping identifier
name string No - Human-readable name
description string No - Detailed description
upstream_url string Yes - Backend server URL
status string No "active" active, maintenance, deprecated, disabled
default_limits object No {} Default rate limits
endpoints array Yes - Endpoint definitions (at least one)
created_at string Auto current time ISO 8601 timestamp
updated_at string Auto current time ISO 8601 timestamp

Rate Limits Object

Field Type Required Default Description
requests_per_second number Yes - Maximum requests per second
burst_size number Yes - Maximum burst size
block_duration number (nanoseconds) No 300000000000 Block duration (5 minutes)
use_sliding_window boolean Auto true Always true (enforced)

Endpoint Object Structure

Field Type Required Default Description
id string Yes - Unique endpoint identifier
path string Yes - Full URL path (e.g., /api/users)
method string Yes - HTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
limits object No API defaults Endpoint-specific rate limits
priority number No 100 Matching priority (lower = higher)
enabled boolean Auto true Always true (enforced)

Status Values

Status Description
active Operational and accepting requests
maintenance Maintenance mode, requests may be rejected
deprecated Deprecated but still operational
disabled Disabled, not accepting requests

Time Values (Nanoseconds)

Duration Nanoseconds Use Case
1 minute 60000000000 Short blocks
5 minutes 300000000000 Standard block duration (default)
10 minutes 600000000000 Medium blocks
15 minutes 900000000000 Secure API blocks
30 minutes 1800000000000 Long blocks

Compiled Rule Object

Returned by Test Rule and Resolve Path endpoints:

Field Type Description
api_id string Parent API identifier
endpoint_id string Matched endpoint identifier
service_id string Service grouping
path string Full request path
method string HTTP method
requests_per_second number Applied RPS limit
burst_size number Applied burst limit
window_size number Time window in nanoseconds
block_duration number Block duration in nanoseconds
use_sliding_window boolean Always true
priority number Endpoint priority
enabled boolean Always true
upstream_url string Backend URL
is_excluded boolean Whether path is excluded

Reverse Proxy Behavior

Key Characteristics

Feature Behavior
Path Forwarding Full paths forwarded as-is (no stripping)
Method Validation Strict matching required (405 if mismatch)
Authentication Handled by middleware layer, not per-endpoint
Rate Limiting Applied before proxying
Request Body Preserved and forwarded correctly

Request Flow

  1. Request arrives: POST http://localhost:8080/api/users
  2. Registry lookup: Finds endpoint with path /api/users and method POST
  3. Method validation: Checks if POST == POST
  4. Rate limiting: Checks limits for the endpoint
  5. Proxy request: Forwards to http://backend:8080/api/users (unchanged path)

Method Mismatch Example

Request:  GET /api/users
Endpoint: POST /api/users
Result:   405 Method Not Allowed
Error:    {"error": "method_not_allowed", "message": "Method GET not allowed for this endpoint. Expected: POST"}

Best Practices

Rate Limit Configuration

Public/High-Traffic APIs:

{
  "requests_per_second": 1000,
  "burst_size": 2000,
  "block_duration": 60000000000
}

Standard APIs:

{
  "requests_per_second": 100,
  "burst_size": 200,
  "block_duration": 300000000000
}

Secure/Sensitive APIs:

{
  "requests_per_second": 10,
  "burst_size": 15,
  "block_duration": 900000000000
}

Endpoint Priority Guidelines

Priority Use Case Example
1-5 Health checks, critical endpoints /health, /ready
10-20 Standard read operations GET /api/users
20-30 Standard write operations POST /api/users
30-50 Destructive operations DELETE /api/users/{id}
50-100 Administrative operations POST /admin/reset

Path Guidelines

DO:

  • Use full paths: /api/users, /api/orders/{id}
  • Include version in path: /api/v1/users
  • Use consistent naming conventions

DON'T:

  • Use relative paths: /users (unless backend expects this)
  • Omit leading slash: api/users
  • Use base_path field (deprecated, ignored by proxy)

Complete Workflow Example

# 1. Create API with multiple endpoints
curl -X POST http://localhost:8080/admin/apis \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer admin-token" \
  -d '{
    "id": "payment-service",
    "service_id": "payments-v1",
    "name": "Payment Service",
    "upstream_url": "http://payment-backend:8080",
    "default_limits": {
      "requests_per_second": 50,
      "burst_size": 100,
      "block_duration": 300000000000
    },
    "endpoints": [
      {
        "id": "health",
        "path": "/health",
        "method": "GET",
        "limits": {"requests_per_second": 1000, "burst_size": 2000},
        "priority": 1
      },
      {
        "id": "list-payments",
        "path": "/api/v1/payments",
        "method": "GET",
        "limits": {"requests_per_second": 50, "burst_size": 100},
        "priority": 10
      },
      {
        "id": "create-payment",
        "path": "/api/v1/payments",
        "method": "POST",
        "limits": {"requests_per_second": 20, "burst_size": 40, "block_duration": 600000000000},
        "priority": 20
      }
    ]
  }'

# 2. Verify creation
curl http://localhost:8080/admin/apis/payment-service \
  -H "Authorization: Bearer admin-token"

# 3. Test routing
curl "http://localhost:8080/admin/apis/resolve?path=/api/v1/payments" \
  -H "Authorization: Bearer admin-token"

# 4. Test the proxy
curl http://localhost:8080/api/v1/payments \
  -H "Authorization: Bearer user-token"

# 5. Monitor metrics
curl http://localhost:8080/admin/metrics/payment-service \
  -H "Authorization: Bearer admin-token"

# 6. Stream real-time events
curl -N http://localhost:8080/admin/apis/events \
  -H "Authorization: Bearer admin-token"

# 7. Export for backup
curl http://localhost:8080/admin/apis/export \
  -H "Authorization: Bearer admin-token" > backup.json

Error Handling

400 Bad Request - Invalid JSON:

{"error": "invalid request body"}

400 Bad Request - Missing Required Fields:

{"error": "id, service_id, and upstream_url are required"}

400 Bad Request - Empty Endpoints:

{"error": "at least one endpoint is required"}

400 Bad Request - Invalid Method:

{"error": "invalid HTTP method: INVALID"}

401 Unauthorized:

{"error": "unauthorized"}

404 Not Found - API:

{"error": "API not found"}

404 Not Found - Endpoint:

{"error": "Endpoint not found"}

405 Method Not Allowed:

{"error": "method_not_allowed", "message": "Method GET not allowed for this endpoint. Expected: POST"}

409 Conflict - Duplicate:

{"error": "API with ID payment-service already exists"}

Additional System Endpoints

Health Check

curl http://localhost:8080/health

Response: OK

Config Info

curl http://localhost:8080/config \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

Legacy Admin Stats

curl http://localhost:8080/admin/stats \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"

Response:

{
  "allowed": 1500,
  "blocked": 50,
  "bot_blocked": 10,
  "in_flight": 5,
  "window_start": "2026-03-10T10:00:00Z"
}

Key Changes

# Change Description
1 Removed base_path requirement Field is now optional per code comments ("base_path is now optional")
2 Removed auth_type from endpoints Authentication handled at middleware layer, not per-endpoint (code comments: "REMOVED: auth_type handling - no longer supported")
3 Removed metadata field Not present in actual API structures
4 Added complete Metrics API section Full documentation for metrics endpoints from metrics_handler.go
5 Fixed endpoints array requirement Validated as required (code checks len(api.Endpoints) == 0)
6 Added strict HTTP method validation Invalid methods rejected with 400 error
7 Removed window_size from user input Auto-calculated by system, not user-configurable
8 Updated reverse proxy behavior Documents no path stripping and strict method matching
9 Added timestamp fields created_at and updated_at present in all responses
10 Corrected nanosecond durations Using actual code values (e.g., 300000000000 for 5 minutes)
11 Added Rate Limit Check (/check) endpoint Complete documentation for dry-run rate limit testing with bot detection, user/IP-based limiting, and excluded paths

Version: 3.0
Last Updated: March 10, 2026
Maintained By: Sraraa