Routes Overview
Routes are the core of ApiCharge's configuration, defining which APIs are monetized and how they're accessed. Each route maps client requests to backend services and provides the foundation for monetization through ApiCharge Subscriptions.
Route Configuration
Routes are configured in the ApiChargeProxy
section of appsettings.json
, which contains both routes and clusters:
{
"ApiChargeProxy": {
"Routes": {
"basic-route": {
"ClusterId": "api-cluster",
"Match": {
"Path": "/api/basic/{**catch-all}"
}
},
"premium-route": {
"ClusterId": "api-cluster",
"Match": {
"Path": "/api/premium/{**catch-all}"
}
}
},
"Clusters": {
"api-cluster": {
"Destinations": {
"destination1": {
"Address": "https://api-backend.example.com"
}
}
}
}
}
}
Route Structure
Each route has the following components:
Route ID
The route ID is a unique identifier for the route, used in quotes and access tokens. In the example above, basic-route
and premium-route
are the route IDs.
ClusterId
The ClusterId links the route to its destination(s) defined in the Clusters section. A cluster represents one or more backend destinations that the request will be forwarded to.
Match
The Match object defines the criteria for matching incoming requests to this route. It supports three main matching types:
- Path: Match requests based on the URL path
- Host: Match requests based on the host header or domain
- Headers: Match requests based on HTTP headers
For detailed information on match configuration, see the Route Matching page.
Metadata (Optional)
Routes can include optional metadata for additional information:
"basic-route": {
"ClusterId": "basic-api-cluster",
"Match": {
"Path": "/api/basic/{**catch-all}"
},
"Metadata": {
"Description": "Basic API with limited features",
"Category": "Public",
"ApiVersion": "v1"
}
}
Metadata is useful for documentation and organization but doesn't affect the route's behavior.
Clusters Configuration
Clusters define where requests should be forwarded once a route is matched. Each cluster can have one or more destinations:
"Clusters": {
"basic-api-cluster": {
"Destinations": {
"destination1": {
"Address": "https://api-backend-1.example.com/basic"
},
"destination2": {
"Address": "https://api-backend-2.example.com/basic"
}
},
"LoadBalancingPolicy": "RoundRobin"
}
}
Destinations
Each destination includes:
- Address: The URL where requests should be forwarded
- Health (optional): Health check configuration
- Metadata (optional): Additional information about the destination
LoadBalancingPolicy
When multiple destinations are specified, you can configure how requests are distributed:
RoundRobin
: Cycles through destinations in orderLeastRequests
: Sends requests to the destination with the fewest active requestsRandom
: Selects destinations randomlyPowerOfTwoChoices
: Selects two random destinations and chooses the one with fewer active requestsFirstAlphabetical
: Selects the first destination by name (useful for testing)
Configuring Routes for Monetization
To monetize a route, you must define quotes for it in the ApiChargeQuotes
section:
{
"ApiChargeQuotes": {
"Quotes": [
{
"RouteId": "basic-route",
"Duration": 3600,
"MicroUnitPrice": 100000,
"RateLimiters": [
{
"$type": "CallCount",
"Count": 100
}
]
},
{
"RouteId": "basic-route",
"Duration": 86400,
"MicroUnitPrice": 500000,
"RateLimiters": [
{
"$type": "CallCount",
"Count": 1000
}
]
}
]
}
}
This configuration defines two different quotes for the basic-route
:
- A 1-hour (3600 seconds) access with 100 calls for 0.01 XLM (100,000 micro units)
- A 24-hour (86400 seconds) access with 1000 calls for 0.05 XLM (500,000 micro units)
Clients can choose which quote best suits their needs when purchasing access.
Protocol Support
ApiCharge routes support a wide range of protocols:
- HTTP/1.1, HTTP/2, and HTTP/3: Standard HTTP APIs
- WebSockets: For persistent, bidirectional connections
- Server-Sent Events (SSE): For server-to-client streaming
- gRPC: For high-performance RPC APIs
ApiCharge automatically applies rate limiting to all these protocols, with protocol-specific handling for streaming connections.
apicharge
header set to probe
, and the middleware will return the associated route ID that can be used to purchase the appropriate subscription. There are other methods such as using header transforms as described in Transforms, but this probe utility offers a simpler approach.
WebSocket and SSE Example
Configure a route for WebSockets and SSE in the same way as HTTP routes:
"websocket-route": {
"ClusterId": "websocket-cluster",
"Match": {
"Path": "/api/ws/{**catch-all}"
}
}
For these streaming protocols, you'll want to consider using the StreamRate limiters to control bandwidth:
{
"RouteId": "websocket-route",
"Duration": 3600,
"MicroUnitPrice": 200000,
"RateLimiters": [
{
"$type": "StreamRateDownload",
"BytesPerSecond": 51200,
"WindowDurationInSeconds": 60
},
{
"$type": "StreamRateUpload",
"BytesPerSecond": 10240,
"WindowDurationInSeconds": 60
}
]
}
This configuration allows for 50KB/s download and 10KB/s upload speeds for WebSocket or SSE connections.
Example Route Configurations
Here are some practical examples of route configurations for different scenarios:
REST API with Different Service Tiers
"ApiChargeProxy": {
"Routes": {
"api-basic": {
"ClusterId": "api-backend",
"Match": {
"Path": "/api/basic/{**catch-all}"
}
},
"api-premium": {
"ClusterId": "api-backend",
"Match": {
"Path": "/api/premium/{**catch-all}"
}
}
},
"Clusters": {
"api-backend": {
"Destinations": {
"api-server": {
"Address": "https://internal-api.example.com/"
}
}
}
}
}
"ApiChargeQuotes": {
"Quotes": [
{
"RouteId": "api-basic",
"Duration": 3600,
"MicroUnitPrice": 50000,
"RateLimiters": [
{
"$type": "CallCount",
"Count": 100
}
]
},
{
"RouteId": "api-premium",
"Duration": 3600,
"MicroUnitPrice": 200000,
"RateLimiters": [
{
"$type": "CallCount",
"Count": 1000
},
{
"$type": "DataLimitDownload",
"Bytes": 10485760
}
]
}
]
}
Content Streaming
"ApiChargeProxy": {
"Routes": {
"video-stream": {
"ClusterId": "media-server",
"Match": {
"Path": "/videos/{**catch-all}"
}
}
},
"Clusters": {
"media-server": {
"Destinations": {
"media-cdn": {
"Address": "https://media-cdn.example.com/"
}
}
}
}
}
"ApiChargeQuotes": {
"Quotes": [
{
"RouteId": "video-stream",
"Duration": 7200,
"MicroUnitPrice": 500000,
"RateLimiters": [
{
"$type": "StreamRateDownload",
"BytesPerSecond": 1048576,
"WindowDurationInSeconds": 60
},
{
"$type": "DataLimitDownload",
"Bytes": 2147483648
}
]
}
]
}
AI Model API
"ApiChargeProxy": {
"Routes": {
"ai-inference": {
"ClusterId": "ai-models",
"Match": {
"Path": "/ai/inference/{**catch-all}"
}
}
},
"Clusters": {
"ai-models": {
"Destinations": {
"inference-server": {
"Address": "http://localhost:8501/"
}
}
}
}
}
"ApiChargeQuotes": {
"Quotes": [
{
"RouteId": "ai-inference",
"Duration": 3600,
"MicroUnitPrice": 1000000,
"RateLimiters": [
{
"$type": "Credit",
"CreditsPerCall": 1,
"TotalCredits": 100
}
]
}
]
}
Next Steps
Now that you understand the basics of route configuration, you can explore:
- Route Matching - Advanced matching patterns for your routes
- Transforms - Modify requests and responses as they pass through ApiCharge
- Rate Limiters - Configure quality of service parameters for your routes