Skip to main content

APIs

Otoroshi introduces a core entity: APIs. This feature marks a major step towards a more API Management-oriented experience by allowing users to manage their APIs as a whole, rather than configuring them route by route.

With the API entity, you can define reusable backends, declare multiple plugin flows that can be applied across different routes, manage consumers (plans) and subscriptions, and track the state of an API throughout its lifecycle.

This evolution unlocks powerful capabilities for building developer portals and brings Otoroshi closer to the expectations of a full-featured API Management platform.

UI page

You can find all APIs here

API entity properties

An API is the top-level entity that groups together routes, backends, flows, documentation, plans, subscriptions, and clients.

PropertyTypeDescription
idstringUnique identifier of the API
namestringDisplay name of the API
descriptionstringDescription of the API
domainstringThe domain on which the API is exposed (e.g., api.mydomain.com)
context_pathstringThe base path prefix for all routes in this API (e.g., /api/v1)
versionstringCurrent version of the API (e.g., 1.0.0)
versionsarray of stringList of all versions of this API
enabledbooleanWhether the API is active and serving traffic
statestringLifecycle state: staging, published, deprecated, or removed
blueprintstringAPI type: REST, GraphQL, gRPC, Http, or Websocket
debug_flowbooleanEnable debug flow logging for all routes
capturebooleanEnable request/response capture
export_reportingbooleanEnable detailed reporting export
groupsarray of stringService groups this API belongs to
tagsarray of stringFree tags for categorization
metadataobjectFree key/value metadata
routesarray of ApiRouteThe routes that compose this API
backendsarray of ApiBackendBackend definitions local to this API
flowsarray of ApiFlowsPlugin flow chains
clients_backend_configarray of ApiBackendClientBackend client configurations
documentationApiDocumentationAPI documentation and developer portal configuration
deploymentsarray of ApiDeploymentDeployment history
clientsarray of ApiClientRegistered API clients
testingApiTestingTesting/draft mode configuration

API lifecycle

An API goes through the following lifecycle states:

staging --> published --> deprecated --> removed
StateDescription
stagingThe API is being designed. Only draft/testing routes are served (if testing is enabled).
publishedThe API is live and serving traffic. Plans can accept subscriptions.
deprecatedThe API is still serving traffic but is marked for removal. No new subscriptions should be created.
removedThe API is deactivated. No traffic is served.

API blueprints

The blueprint field indicates the type of API being managed:

  • REST: Standard RESTful HTTP APIs
  • GraphQL: GraphQL APIs
  • gRPC: gRPC services
  • Http: Generic HTTP services
  • Websocket: WebSocket-based APIs

Routes

An API is composed of multiple routes. Each route describes an HTTP endpoint exposed by the API (e.g., GET /users, POST /orders).

A route is composed of a frontend (describing the entry point: domain, path, methods, headers), a reference to a backend, and a reference to a flow (plugin chain).

PropertyTypeDescription
idstringUnique identifier of the route
namestringDisplay name of the route (optional)
enabledbooleanWhether this route is active (default: true)
frontendobjectFrontend configuration (domains, paths, headers, methods, query, strip_path, exact)
backendstringReference to a backend ID (either a local API backend or a global stored backend)
flow_refstringReference to a flow ID from this API's flows list

The route's frontend paths are automatically prefixed with the API's domain and context_path. For example, if the API has domain: api.example.com and context_path: /v1, and a route has a frontend path /users, the effective matching path will be api.example.com/v1/users.

A route can be enabled or disabled independently of the API's activation.

Route JSON example

{
"id": "route_users_list",
"enabled": true,
"name": "List users",
"frontend": {
"domains": ["oto.tools/users"],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": ["GET"]
},
"backend": "api_backend_abc123",
"flow_ref": "default_plugin_chain"
}

Backends

A backend represents a list of target servers, along with its load balancing, health checks, and connection settings.

Backends can be defined locally within the API (in the backends array) or reference a global stored backend by its ID. This makes backends reusable across multiple APIs and routes.

PropertyTypeDescription
idstringUnique identifier of the backend
namestringDisplay name of the backend
backendobjectFull backend configuration (targets, root, rewrite, load balancing, health checks, TLS, etc.) following the NgBackend format
clientstringReference to a backend client configuration ID from clients_backend_config

Backend JSON example

{
"id": "api_backend_abc123",
"name": "Users service backend",
"backend": {
"targets": [
{
"id": "target_1",
"hostname": "users-service.internal",
"port": 8080,
"tls": false,
"weight": 1
}
],
"root": "/",
"rewrite": false,
"load_balancing": { "type": "RoundRobin" }
},
"client": "default_backend_client"
}

Backend clients

Backend clients define the HTTP client configuration used when connecting to backend targets. They are referenced by backends using the client field.

PropertyTypeDescription
idstringUnique identifier
namestringDisplay name
clientobjectClient configuration (retries, timeouts, circuit breaker, connection pool, etc.) following the NgClientConfig format

Backend client JSON example

{
"id": "default_backend_client",
"name": "Default client",
"client": {
"useCircuitBreaker": true,
"retries": 1,
"maxErrors": 20,
"retryInitialDelay": 50,
"backoffFactor": 2,
"callAndStreamTimeout": 120000,
"callTimeout": 30000,
"idleTimeout": 60000,
"globalTimeout": 30000,
"connectionTimeout": 10000
}
}

Flows

A flow is a named collection of plugins. Plugins are applied between the frontend and the backend (and vice versa) during request processing. Each route references a flow by ID.

PropertyTypeDescription
idstringUnique identifier of the flow
namestringDisplay name of the flow
pluginsobjectPlugin chain following the NgPlugins format

A default flow named default_plugin_chain is automatically created with the OverrideHost plugin. You can add multiple flows to apply different plugin chains to different routes within the same API.

You can check the list of available plugins here.

Flow JSON example

{
"id": "authenticated_flow",
"name": "Authenticated flow",
"plugins": {
"slots": [
{
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"enabled": true,
"include": [],
"exclude": [],
"config": {}
},
{
"plugin": "cp:otoroshi.next.plugins.ApikeyCalls",
"enabled": true,
"include": [],
"exclude": [],
"config": {}
}
]
}
}

Documentation

The API documentation subsystem powers developer portal experiences. It supports pages, navigation sidebars, search, banners, logos, and external content sources.

PropertyTypeDescription
enabledbooleanWhether the documentation is active
sourceobjectOptional remote source to fetch documentation content (URL, headers, timeout, follow_redirects)
homeobjectHome page resource
logoobjectLogo resource
referencesarrayList of external reference links (title, description, link, icon)
resourcesarrayList of documentation resources/pages
navigationarraySidebar navigation structure (categories and links)
redirectionsarrayURL redirections (from -> to)
footerobjectFooter resource (optional)
searchobjectSearch configuration (enabled: boolean)
bannerobjectBanner resource (optional)
plansarray of ApiDocumentationPlanSubscription plans with access modes and pricing
metadataobjectDocumentation metadata
tagsarray of stringDocumentation tags

Documentation resources

Each resource in the documentation can contain:

PropertyTypeDescription
patharray of stringPath segments for URL routing
titlestringPage title
descriptionstringPage description
content_typestringContent type (default: text/markdown)
text_contentstringInline text content
json_contentobjectInline JSON content
base64_contentstringBase64-encoded binary content
urlstringRemote URL to fetch content from
site_pagebooleanWhether this resource is a standalone site page
transformstringContent transformation to apply

Plans

Plans (also referred to as consumers in the UI) define security policies and pricing for API access. Each plan specifies an access mode that determines how clients authenticate when calling the API.

PropertyTypeDescription
idstringUnique identifier of the plan
namestringDisplay name of the plan
descriptionstringDescription of the plan
statusstringPlan status: staging, published, deprecated, or closed
access_mode_configuration_typestringAccess mode type (see below)
access_mode_configurationobjectAccess mode configuration (depends on type)
pricingApiPricingPricing configuration
tagsarray of stringTags
metadataobjectMetadata

Access modes

Otoroshi supports the following access modes for plans:

ModeDescriptionPlugins applied
keylessNo authentication required. Open access.None
apikeyRequires a valid API key. Configurable key patterns, restrictions, quotas, and rotation.ApikeyCalls
jwtRequires a valid JWT token with expected signature.JwtUserExtractor
mtlsRequires a valid TLS client certificate matching configured subject/issuer patterns.HasClientCertMatchingValidator
oauth2-localOAuth2 client credentials flow with local token generation. Clients obtain a JWT to call other routes.ApikeyCalls + client credentials endpoint
oauth2-remoteOAuth2 with remote token introspection via an external OIDC provider.OIDCJwtVerifier

Apikey access mode configuration

PropertyTypeDescription
clientIdPatternstringRegex pattern for generated client IDs
clientNamePatternstringRegex pattern for generated client names
descriptionstringDescription for generated API keys
authorizedEntitiesarrayEntities the API key is authorized on
enabledbooleanWhether generated keys are enabled
readOnlybooleanWhether generated keys are read-only
allowClientIdOnlybooleanAllow authentication with client ID only (no secret)
constrainedServicesOnlybooleanRestrict to constrained services only
restrictionsobjectAccess restrictions (allowed/forbidden paths and methods)
rotationobjectKey rotation configuration (enabled, rotationEvery, gracePeriod)
validUntilnumberExpiration timestamp (milliseconds)
tagsarray of stringTags for generated keys
metadataobjectMetadata for generated keys

Plan JSON example

{
"id": "plan_free_tier",
"name": "Free Tier",
"description": "Free access with rate limiting",
"status": "published",
"access_mode_configuration_type": "apikey",
"access_mode_configuration": {
"enabled": true,
"readOnly": false,
"allowClientIdOnly": false,
"constrainedServicesOnly": false,
"restrictions": {
"enabled": false
},
"rotation": {
"enabled": false,
"rotationEvery": 744,
"gracePeriod": 168
},
"tags": [],
"metadata": {}
},
"pricing": {
"id": "pricing_free",
"name": "Free",
"enabled": true,
"price": 0,
"currency": "EUR",
"params": {}
},
"tags": [],
"metadata": {}
}

Pricing

Plans can include pricing information for monetization purposes.

PropertyTypeDescription
idstringUnique identifier
namestringPricing plan name
enabledbooleanWhether pricing is active
pricenumberPrice amount
currencystringCurrency code (e.g., EUR, USD)
paramsobjectAdditional pricing parameters

Subscriptions

End-users (developers, portals, machines) can subscribe to published plans. A subscription contains information about the subscriber and references to the generated credentials (API key, certificate, JWT, etc.).

PropertyTypeDescription
idstringUnique identifier
namestringDisplay name
descriptionstringDescription
enabledbooleanWhether the subscription is active
api_refstringReference to the parent API
plan_refstringReference to the plan
owner_refstringReference to the subscribing client
subscription_kindstringKind of subscription: apikey, mtls, keyless, oauth2-local, oauth2-remote, jwt
token_refsarray of stringReferences to generated credentials (API key IDs, certificate IDs, etc.)
datesobjectLifecycle timestamps (see below)
tagsarray of stringTags
metadataobjectMetadata

Subscription dates

PropertyTypeDescription
created_atnumberTimestamp when subscription was created
processed_atnumberTimestamp when subscription was processed
started_atnumberTimestamp when subscription became active
paused_atnumberTimestamp when subscription was paused
ending_atnumberTimestamp when subscription will end
closed_atnumberTimestamp when subscription was closed

Subscription JSON example

{
"id": "subscription_abc123",
"name": "ACME Corp subscription",
"description": "Free tier subscription for ACME Corp",
"enabled": true,
"api_ref": "api_users_service",
"plan_ref": "plan_free_tier",
"owner_ref": "client_acme",
"subscription_kind": "apikey",
"token_refs": ["apikey_xyz789"],
"dates": {
"created_at": 1710000000000,
"processed_at": 1710000000000,
"started_at": 1710000000000,
"paused_at": 1710000000000,
"ending_at": 1710000000000,
"closed_at": 1710000000000
},
"tags": [],
"metadata": {}
}

API clients

Clients represent the consumers that subscribe to your API. They are lightweight entities used to identify subscribers.

PropertyTypeDescription
idstringUnique identifier
namestringClient name
descriptionstringDescription
tagsarray of stringTags
metadataobjectMetadata

Testing

The testing configuration allows you to test draft routes before publishing the API. When testing is enabled, Otoroshi generates special routes from the API's draft with a custom header requirement.

PropertyTypeDescription
enabledbooleanWhether testing mode is active
headerKeystringHeader name required to access draft routes (default: X-OTOROSHI-TESTING)
headerValuestringExpected header value (auto-generated UUID)

When testing is enabled:

  1. Draft routes are built from the latest saved draft of the API
  2. Each draft route requires the testing header (X-OTOROSHI-TESTING: <value>) to be accessible
  3. This allows you to test changes without affecting published routes

Deployments

Deployments track the history of API publications. Each time an API is published (its state transitions from staging to published), a deployment record is created.

PropertyTypeDescription
idstringUnique identifier
apiRefstringReference to the API
ownerstringWho performed the deployment
atnumberTimestamp of the deployment
apiDefinitionobjectSnapshot of the API definition at deployment time
versionstringVersion of the API at deployment time

OpenAPI import

Otoroshi can generate an API entity from an OpenAPI specification. When importing from an OpenAPI document:

  • The API name, description, and version are extracted from the info section
  • Server URLs are mapped to backend targets
  • Each path and method combination is converted to an API route
  • Both JSON and YAML formats are supported

Complete API JSON example

{
"id": "api_users_service",
"name": "Users Service",
"description": "API for managing users",
"domain": "api.example.com",
"context_path": "/v1",
"version": "1.0.0",
"versions": ["1.0.0"],
"enabled": true,
"state": "published",
"blueprint": "REST",
"debug_flow": false,
"capture": false,
"export_reporting": false,
"groups": ["default"],
"tags": ["users", "core"],
"metadata": {
"team": "platform"
},
"backends": [
{
"id": "users_backend",
"name": "Users backend",
"backend": {
"targets": [
{
"id": "target_1",
"hostname": "users-service.internal",
"port": 8080,
"tls": false,
"weight": 1
}
],
"root": "/",
"rewrite": false,
"load_balancing": { "type": "RoundRobin" }
},
"client": "default_backend_client"
}
],
"clients_backend_config": [
{
"id": "default_backend_client",
"name": "Default client config",
"client": {
"useCircuitBreaker": true,
"retries": 1,
"callTimeout": 30000,
"globalTimeout": 30000
}
}
],
"flows": [
{
"id": "default_plugin_chain",
"name": "Default flow",
"plugins": {
"slots": [
{
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"enabled": true,
"include": [],
"exclude": [],
"config": {}
}
]
}
}
],
"routes": [
{
"id": "route_list_users",
"enabled": true,
"name": "List users",
"frontend": {
"domains": ["oto.tools/users"],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": ["GET"]
},
"backend": "users_backend",
"flow_ref": "default_plugin_chain"
},
{
"id": "route_create_user",
"enabled": true,
"name": "Create user",
"frontend": {
"domains": ["oto.tools/users"],
"strip_path": true,
"exact": false,
"headers": {},
"query": {},
"methods": ["POST"]
},
"backend": "users_backend",
"flow_ref": "default_plugin_chain"
}
],
"documentation": {
"enabled": true,
"plans": [
{
"id": "plan_free",
"name": "Free Tier",
"description": "Free access with API key",
"status": "published",
"access_mode_configuration_type": "apikey",
"access_mode_configuration": {
"enabled": true,
"readOnly": false,
"allowClientIdOnly": false,
"tags": [],
"metadata": {}
},
"pricing": {
"id": "pricing_free",
"name": "Free",
"enabled": false,
"price": 0,
"currency": "EUR",
"params": {}
}
}
],
"home": {},
"logo": {},
"references": [],
"resources": [],
"navigation": [],
"redirections": [],
"search": { "enabled": true },
"metadata": {},
"tags": []
},
"clients": [
{
"id": "client_acme",
"name": "ACME Corp",
"description": "ACME Corp developer account",
"tags": [],
"metadata": {}
}
],
"testing": {
"enabled": false,
"headerKey": "X-OTOROSHI-TESTING",
"headerValue": "secret-test-value"
},
"deployments": []
}

Admin API

The API entity can be managed through the admin API:

GET    /api/apis                     # List all APIs
POST /api/apis # Create a new API
GET /api/apis/:id # Get an API by ID
PUT /api/apis/:id # Update an API
DELETE /api/apis/:id # Delete an API
PATCH /api/apis/:id # Partially update an API

Subscriptions are managed at:

GET    /api/api-subscriptions        # List all subscriptions
POST /api/api-subscriptions # Create a subscription
GET /api/api-subscriptions/:id # Get a subscription
PUT /api/api-subscriptions/:id # Update a subscription
DELETE /api/api-subscriptions/:id # Delete a subscription
  • Routes - The route entity that API routes are converted into at runtime
  • Backends - Global reusable backends that can be referenced by API backends
  • API Keys - Credentials generated when subscribing with apikey access mode
  • Certificates - Certificates used with mtls access mode
  • JWT Verifiers - Verifiers used with jwt and oauth2-remote access modes