Visit APIToGo on LinkedIn
  • Documentation
  • Components
  • Themes
Quickstart
CLI
MCP
Configuration
    Configuration overviewPortalProtect your API with the gatewaySign-inPlansAPI referenceMake config
Look and feel
Writing
Guides
Deployment
powered by apitogo
Configuration

Protect your API with the gateway

The gateway sits in front of an API you already host. It checks who is calling, limits how often, and passes only the calls you allow to your API. You do not move your API.

Code
callers ──► APItoGo gateway ──► your API (stays where it is) │ checks the login token │ limits calls │ allows only the calls in your OpenAPI file └ your real API address stays hidden

You set it up in one file, apitogo.config.json, in a gateway section.

The smallest setup

Code
{ "version": 2, "gateway": { "origin": { "mode": "proxy", "url": "https://api.example.com", "healthPath": "/health" }, "specs": ["apis/openapi.yaml"], "auth": { "mode": "oidc", "metadataUrl": "https://login.example.com/.well-known/openid-configuration", "issuers": ["https://login.example.com/"], "audiences": ["my-api"] }, "policies": { "access": { "jwt": true, "apiKey": false }, "rateLimit": { "calls": 60, "periodSeconds": 60 }, "operations": { "public": ["GET /health"] } } } }

apitogo add gateway writes the first part for you. The rest you write yourself, and the sections below explain every value.

1. Your API (origin and specs)

SettingWhat to put thereWhere to get it
origin.modeproxy: your API stays where it is.Always proxy for an API you host.
origin.urlThe address of your API. It must be https://.You already know it. It is where your API answers today.
origin.healthPathA path the platform can call to see that your API is alive, for example /health.A cheap call on your API that needs no login.
specsThe OpenAPI file or files that describe your API.Your API's openapi.yaml, or the file your framework generates.

The gateway only lets through the calls listed in your OpenAPI file. A call that is not in the file is refused, so a forgotten path never leaks.

2. Who may call (auth)

With "mode": "oidc" the caller sends a login token (a JWT) with each call: Authorization: Bearer <token>. The token comes from your own login provider, for example Auth0, Microsoft Entra ID, Okta or Keycloak. The gateway checks that the token is genuine, is from your provider and is meant for your API.

You must give all three of these values. If one is missing, the deploy is blocked, so a settings mistake can never leave your API open.

SettingWhat it isHow to find it
metadataUrlThe address where the gateway reads your provider's public keys, so it can check a token's signature.Your issuer address plus /.well-known/openid-configuration.
issuersWho is allowed to issue tokens. It must match the iss value in your tokens exactly.The issuer field inside the metadata document (see below).
audiencesWho the token is meant for. It must match the aud value in your tokens.The identifier you gave your API at your provider.

Find the values in four steps

  1. Find your provider's issuer address. It is on the provider's dashboard or in its docs. Typical shapes are in the table below.
  2. Open the metadata address in a browser. Add /.well-known/openid-configuration to the issuer address. You see a JSON document. If you see an error, the address is wrong.
  3. Copy the issuer value from that document into issuers, character for character, including a trailing / if it has one.
  4. Use the identifier of your API as audiences. You create this identifier at your provider when you register your API. It is often called API identifier, audience or application ID URI.

Typical values by provider

These are typical shapes. Always confirm them in your provider's dashboard.

ProviderIssuerAudience
Auth0https://YOUR-TENANT.auth0.com/ (with the trailing /)The API identifier of your API in Auth0
Microsoft Entra IDhttps://login.microsoftonline.com/TENANT-ID/v2.0Your API's Application ID URI, for example api://CLIENT-ID
Oktahttps://YOUR-ORG.okta.com/oauth2/default (or your own authorization server)The audience set on that authorization server
Keycloakhttps://HOST/realms/YOUR-REALMThe client or audience you configured for your API

In every case the metadata address is the issuer plus /.well-known/openid-configuration.

Check a real token

Ask your provider for a token for your API, then read what is inside it. The values iss and aud must match your issuers and audiences:

TerminalCode
node -p "JSON.parse(Buffer.from(process.argv[1].split('.')[1],'base64url').toString())" "PASTE-THE-TOKEN-HERE"

A token is a login credential. Read it on your own computer, as above, and never share it.

The most common mistakes

What you seeUsual cause
Every call answers 401 although the token looks rightissuers or audiences does not match iss or aud in the token. A trailing / is enough to break it.
apitogo check or deploy says the auth settings are incompleteOne of metadataUrl, issuers or audiences is empty. All three are needed.
The metadata address shows an error in the browserThe issuer address is wrong, or your provider uses a different path. Check its docs.

Not available yet: "mode": "identity" (APItoGo's own sign-up and login for your end users) is a planned service. For now, use oidc with your own provider.

3. The rules (policies)

Rules go in gateway.policies. Write them by hand: they are a few lines each.

access: who gets in

Code
"access": { "jwt": true, "apiKey": false }
SettingEffect
jwttrue: a valid login token is required.
apiKeytrue: a key in the Ocp-Apim-Subscription-Key header is required. Keys need the plans service, which is not available yet.

Set access yourself and do not rely on the default.

operations: open a call to everyone, or close it

Code
"operations": { "public": ["GET /health"], "deny": ["DELETE /orders"] }

Each entry is METHOD /path, exactly as in your OpenAPI file.

ListEffect
publicAnyone can call it, with no token. Use it for a health check or a public price list.
denyThe gateway always refuses it, even with a valid token.

Every other call needs a login.

rateLimit and quota: how often

Code
"rateLimit": { "calls": 60, "periodSeconds": 60 }, "quota": { "calls": 10000, "periodDays": 30 }
SettingEffect
rateLimitAt most calls calls in every periodSeconds seconds. Extra calls get 429. Use it to protect your API from bursts.
quotaAt most calls calls in every periodDays days. Use it for a monthly allowance.

cors: which websites may call from a browser

Code
"cors": ["https://app.example.com"]

A browser only lets a web page call your API if the API allows that page's site. List each site as https://host only: no path and no trailing /. An entry like https://app.example.com/ is refused by apitogo check.

Keep your API from being called directly

Your API has a public address, so someone could skip the gateway. Make your API accept calls only with a secret that only the gateway sends:

Code
"origin": { "mode": "proxy", "url": "https://api.example.com", "auth": { "type": "header", "name": "X-Gateway-Secret", "value": "secret:GATEWAY_SECRET" } }
TerminalCode
apitogo secrets set GATEWAY_SECRET

The value is a reference, never the secret itself. The secret is stored encrypted and never shown again. Then make your API refuse any call without that header.

Run your API on the platform (managed origin)

If you have no place to host your API, the platform can run your code. Set the origin mode to managed and point source at the folder with your code:

Code
"gateway": { "origin": { "mode": "managed", "source": "backend", "runtime": "nodejs", "runtimeVersion": "NODE_22_LTS", "healthPath": "/health", "exclude": ["tests/"] }, "specs": ["openapi.json"] }
FieldMeaning
sourceFolder with your code, relative to the config. Files in its .gitignore and in exclude are not uploaded.
runtimenodejs, python or dotnet.
runtimeVersionFor example NODE_22_LTS. The platform lists the allowed values.
healthPathPath the platform probes to check that your API is up.
excludeMore paths to leave out, in .gitignore syntax.

apitogo add gateway --origin managed makes the source folder when it does not exist and tells you it is empty; put your code there. apitogo check warns while the folder has no code.

apitogo project create prepares the hosting for your code. apitogo deploy then uploads the OpenAPI file and the config, uploads your code and waits until it runs, and the gateway starts sending calls to it. A deploy with the same code uploads nothing. A .NET project is published for you (this needs the .NET SDK on your machine), or you can point source at a folder that is already published.

Your code can also be reached by its own address, so check that a call came through the gateway. The platform gives your code two settings for this: APITOGO_ORIGIN_SECRET_HEADER (the header name) and APITOGO_ORIGIN_SECRET (the value). The gateway sends that header with every call. Refuse any request without it, as in Keep your API from being called directly:

Code
const header = process.env.APITOGO_ORIGIN_SECRET_HEADER.toLowerCase(); if (req.headers[header] !== process.env.APITOGO_ORIGIN_SECRET) { res.writeHead(403).end(); return; }

4. Try it and check it

Run these before you deploy:

TerminalCode
apitogo check apitogo plan

check finds mistakes in the file, offline. plan shows what a deploy would change and changes nothing. Then deploy and test the address that apitogo status shows:

TerminalCode
apitogo deploy --only gateway curl -i https://YOUR-GATEWAY-ADDRESS/health curl -i https://YOUR-GATEWAY-ADDRESS/orders
AnswerMeaning
200 on a public callThe call is open and your API answered.
401 on a call without a tokenThe gateway is protecting that call.
404The path is not in your OpenAPI file.
429The rate limit was reached.
502 or 504Your API did not answer. Check origin.url and healthPath.

A change is live a few seconds after deploy reports it ready: the gateway keeps answering with the previous rules for up to about ten seconds. If a test right after a deploy shows the old behavior, wait a moment and try again. The same delay applies when you remove a gateway: its keys stop working within seconds, not at the same instant.

Last modified on November 10, 2026
PortalSign-in
On this page
  • The smallest setup
  • 1. Your API (origin and specs)
  • 2. Who may call (auth)
    • Find the values in four steps
    • Typical values by provider
    • Check a real token
    • The most common mistakes
  • 3. The rules (policies)
    • access: who gets in
    • operations: open a call to everyone, or close it
    • rateLimit and quota: how often
    • cors: which websites may call from a browser
    • Keep your API from being called directly
  • Run your API on the platform (managed origin)
  • 4. Try it and check it
JSON
JSON
JSON
JSON
JSON
JSON
JSON
Javascript