Skip to main content

APIs

ALPHA

Why the API entity?​

In a typical API gateway setup, each HTTP endpoint is configured as an individual route. This works well for simple use cases, but as your platform grows, you end up with dozens or hundreds of routes that logically belong to the same service — they share the same backends, the same security policies, the same documentation. Managing them individually becomes tedious and error-prone.

The API entity solves this problem by providing a higher-level abstraction that groups everything related to a single API under one roof:

  • Multiple routes — define all the endpoints of your API (GET /users, POST /orders, etc.) in one place, with a shared domain and context path
  • Shared backends — define backend targets once and reuse them across routes, instead of duplicating target configurations
  • Plugin flows — create named plugin chains (authentication, rate limiting, transformations, etc.) and assign them to different routes as needed
  • Consumer plans — define who can access your API and how (API keys, JWT, mTLS, OAuth2), with pricing and quotas
  • Subscriptions — let developers or machines subscribe to your plans and receive auto-generated credentials
  • Lifecycle management — track your API from staging through published, deprecated, and removed
  • Testing mode — test draft changes safely before publishing, using a special header to access draft routes
  • Versioning and deployments — keep a history of published versions with full snapshots
  • Built-in documentation — attach pages, navigation, logos, and banners to power a developer portal

In short, the API entity turns Otoroshi from a route-level proxy into a full API Management platform: you design, secure, publish, version, and document your APIs in one place.

How it works at runtime​

When Otoroshi starts or when an API is updated, each API is converted into a set of standard NgRoute objects that the proxy engine uses for request matching and forwarding. This conversion happens transparently:

  1. Each API route's frontend paths are prefixed with the API's domain and context_path (e.g., a route with path /users on an API with domain api.example.com and context path /v1 becomes api.example.com/v1/users)
  2. Backend references are resolved — either from the API's local backends or from global stored backends
  3. The plugin flow referenced by each route is attached as the route's plugin chain
  4. Published consumer plans inject the appropriate security plugins (API key validation, JWT verification, mTLS checks, etc.) into each route automatically. Whatever the plan kind, the caller is turned into an API key consumer whose quotas and restrictions are enforced at the end of the access validation phase
  5. If testing mode is enabled, additional draft routes are generated that require a special header to access

This means you get the organizational benefits of the API entity without any runtime overhead — under the hood, Otoroshi's engine processes the same optimized route structures it always has.

APIs vs. Routes — when to use which​

Otoroshi offers two levels of abstraction for configuring your HTTP traffic, and they serve different purposes:

Routes: low-level HTTP routing​

A route is a low-level, flexible building block. It gives you direct control over every aspect of HTTP proxying: exact domain matching, path patterns, headers, the full plugin chain, backend targets, TLS settings, etc. There are no constraints — you can wire anything to anything.

Routes are the right choice when:

  • You need maximum flexibility and fine-grained control over how a specific request is handled
  • You are proxying traffic that doesn't fit the "managed API" model (static assets, internal redirects, catch-all rules, WebSocket tunnels, TCP proxying, etc.)
  • You want to set up a quick one-off reverse proxy rule without the overhead of lifecycle management

APIs: structured API Management​

An API is a higher-level, more opinionated entity built on top of routes. It adds structure and guardrails: a shared domain, a context path, a lifecycle (staging → published → deprecated → removed), consumer plans, subscriptions, versioning, deployments, and documentation.

This structure is deliberate — it trades some of the route-level flexibility for consistency and governance:

  • All routes in an API share the same domain and context path, so your URL scheme stays coherent
  • Security policies are defined as consumer plans rather than per-route plugin configurations, making it easier to reason about who has access to what
  • Lifecycle states prevent accidental exposure of work-in-progress endpoints
  • Subscriptions and credential generation provide a self-service workflow for API consumers
  • Deployment history gives you traceability of what was published and when

APIs are the right choice when:

  • You are exposing a service to external or internal consumers and want to manage access in a structured way
  • You need lifecycle management, versioning, and deployment tracking
  • You want to offer subscription plans with auto-generated credentials (API keys, JWT, OAuth2, mTLS)
  • You are building a developer portal

Under the hood, it's all routes​

The key insight is that APIs are ultimately compiled down to routes at runtime. An API is a management-layer abstraction — it doesn't introduce a different proxy engine. When you create an API with 5 endpoints, Otoroshi generates 5 NgRoute objects behind the scenes, with the domain/context path prefixed, the backends resolved, and the consumer plan security plugins injected. So the choice between APIs and routes is really about how you want to organize and govern your configuration, not about runtime behavior.

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.

An API written by a remote catalog takes its state from the source of the catalog: each deploy of the catalog is a deploy of the API, without a draft.

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": [
{
"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)
rateLimitingobjectRate limiting of the plan: { "strategy": { ... } }. Every consumer of the plan is rate limited with that strategy. Defaults to the legacy strategy with the default quotas
pluginsobjectPlugin chain applied for the consumers of this plan. See plan plugins
validationobjectHow subscriptions are validated: { "kind": "auto" | "manual" | "webhook" | "workflow" }
visibilityobjectVisibility of the plan in the developer portal: { "kind": "public" | "semi_public" | "private" | "custom" }
pricingApiPricingPricing configuration
tagsarray of stringTags
metadataobjectMetadata

Access modes​

Whatever the access mode, a published plan turns the caller into a consumer, and a consumer is always an API key: the quotas, restrictions and rotation of the plan are enforced the same way for a public plan and for a plan asking for client credentials. See API consumers and plugin flows for the whole picture.

ModeDescriptionPlugins applied
keylessNo credential required. The consumer is derived from an expression, the caller IP address by defaultNgExpressionApikeyExtractor
apikeyRequires a valid API key. Configurable key patterns, restrictions, quotas, and rotationApikeyCalls
jwtRequires a valid JWT token. The consumer is the client id claim of the tokenNgJwtApikeyExtractor
mtlsRequires a TLS client certificate matching the configured subject/issuer patternsNgClientCertApikeyExtractor
oauth2-localOAuth2 client credentials flow with local token generation. Clients obtain a JWT to call other routesApikeyCalls + client credentials endpoint
oauth2-remoteOAuth2 token verified against the OIDC settings of an auth. module. The consumer is the client id claim of the tokenNgOidcApikeyExtractor

Every published plan also adds NgApiConsumerEnforcer on the routes of the API. It runs last, requires a consumer, and is the only place where a call is counted against the quotas of the plan.

All the access modes but apikey and oauth2-local generate an API key for a consumer they have never seen, and they all share the create_if_missing flag for that. When it is on, the default, the generated API key is persisted and shows up in the UI. When it is off, the identity only lives for the duration of the call. In both cases the caller is served and its consumption is counted.

Keyless access mode configuration​

PropertyTypeDefaultDescription
exprstring${req.ip}Expression building the consumer identity of a public call
create_if_missingbooleantruePersist the generated API key
warning

A missing value resolves to no-header-<field> and puts every such caller on one shared quota. Use an empty default (${req.headers.x-consumer:}) to have those calls rejected instead.

JWT access mode configuration​

PropertyTypeDefaultDescription
verifierstringID of the JWT verifier validating the token
client_id_pathstringclient_idClaim holding the client id of the consumer. A JSON path such as $.azp works too
create_if_missingbooleantruePersist the generated API key

mTLS access mode configuration​

PropertyTypeDefaultDescription
regex_subject_dnsarray of string[]Regex patterns the subject DN of the client certificate may match
regex_issuer_dnsarray of string[]Regex patterns the issuer DN may match. A certificate matching either list is accepted. Both lists empty means any trusted certificate is accepted
client_id_fieldstringnullDN attribute holding the client id (UID, CN, ...). Left empty, the identity is derived from the whole subject and the serial number. A certificate missing the named attribute is rejected
create_if_missingbooleantruePersist the generated API key

OAuth2 remote access mode configuration​

PropertyTypeDefaultDescription
verifierstringID of the auth. module whose OIDC settings validate the token
client_id_pathstringclient_idClaim holding the client id of the consumer (client_id, azp or cid depending on the vendor)
fetch_userbooleanfalseCall the userinfo endpoint of the module and store the profile of the token holder in a metadata of the API key. The call stays a consumer call, no user session is attached to it
user_metadata_keystringuser_profileMetadata key holding that profile
create_if_missingbooleantruePersist the generated API key

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

Rate limiting​

The rateLimiting property of a plan holds the throttling strategy handed over to every consumer of the plan, whether it got its API key through a subscription or was generated on the fly by the access mode. A plan without an explicit strategy falls back on the legacy one with the default quotas, which is what an API key created by hand gets.

{
"rateLimiting": {
"strategy": {
"id": "LegacyThrottlingStrategyConfig",
"quota": { "window": 100, "daily": 10000, "monthly": 300000 }
}
}
}

Plan plugins​

A plan can bring its own plugins. They are applied on top of the plugin chain of the route, for the consumers of that plan only. See API consumers and plugin flows.

PropertyTypeDefaultDescription
pluginsarray[]Plugin chain, same format as the plugins of a route
flow_refstringnullID of one of the flows of the API to use instead of listing the plugins here. An inline chain extends the referenced flow, it does not replace it
overridesbooleanfalseReplace the plugins of the route instead of extending them. The pre-route and access validation plugins that already ran are kept, as are the global plugins
{
"plugins": {
"overrides": false,
"flow_ref": "authenticated_flow",
"plugins": [
{
"plugin": "cp:otoroshi.next.plugins.AdditionalHeadersOut",
"enabled": true,
"include": [],
"exclude": [],
"config": {
"headers": { "X-Plan": "${apikey.api.plan}" }
}
}
]
}
}

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": {}
},
"rateLimiting": {
"strategy": {
"id": "LegacyThrottlingStrategyConfig",
"quota": { "window": 10, "daily": 1000, "monthly": 10000 }
}
},
"plugins": {
"plugins": [],
"overrides": false,
"flow_ref": null
},
"validation": { "kind": "auto", "config": {} },
"visibility": { "kind": "public", "config": {} },
"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. It has to be the access mode of the plan
token_refsarray of stringReferences to generated credentials (API key IDs, certificate IDs, etc.)
datesobjectLifecycle timestamps (see below)
tagsarray of stringTags
metadataobjectMetadata

A subscription is refused with a 400 when its subscription_kind is not the access mode of its plan. A subscription to an apikey or an oauth2-local plan is given an API key built from the plan, and referenced in token_refs as {"apikey": "<client id>"}: the consumers of these plans call with an API key, and a subscription is the only way to get one. The other access modes build their consumer at call time, their subscriptions have nothing to generate.

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": [
{
"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
  • API consumers and plugin flows - How a plan identifies its callers and how plan plugins are applied