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
You set it up in one file, apitogo.config.json, in a gateway section.
The smallest setup
Code
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)
| Setting | What to put there | Where to get it |
|---|---|---|
origin.mode | proxy: your API stays where it is. | Always proxy for an API you host. |
origin.url | The address of your API. It must be https://. | You already know it. It is where your API answers today. |
origin.healthPath | A 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. |
specs | The 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.
| Setting | What it is | How to find it |
|---|---|---|
metadataUrl | The 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. |
issuers | Who is allowed to issue tokens. It must match the iss value in your tokens exactly. | The issuer field inside the metadata document (see below). |
audiences | Who 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
- Find your provider's issuer address. It is on the provider's dashboard or in its docs. Typical shapes are in the table below.
- Open the metadata address in a browser. Add
/.well-known/openid-configurationto the issuer address. You see a JSON document. If you see an error, the address is wrong. - Copy the
issuervalue from that document intoissuers, character for character, including a trailing/if it has one. - 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.
| Provider | Issuer | Audience |
|---|---|---|
| Auth0 | https://YOUR-TENANT.auth0.com/ (with the trailing /) | The API identifier of your API in Auth0 |
| Microsoft Entra ID | https://login.microsoftonline.com/TENANT-ID/v2.0 | Your API's Application ID URI, for example api://CLIENT-ID |
| Okta | https://YOUR-ORG.okta.com/oauth2/default (or your own authorization server) | The audience set on that authorization server |
| Keycloak | https://HOST/realms/YOUR-REALM | The 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:
Code
A token is a login credential. Read it on your own computer, as above, and never share it.
The most common mistakes
| What you see | Usual cause |
|---|---|
Every call answers 401 although the token looks right | issuers 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 incomplete | One of metadataUrl, issuers or audiences is empty. All three are needed. |
| The metadata address shows an error in the browser | The 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, useoidcwith 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
| Setting | Effect |
|---|---|
jwt | true: a valid login token is required. |
apiKey | true: 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
Each entry is METHOD /path, exactly as in your OpenAPI file.
| List | Effect |
|---|---|
public | Anyone can call it, with no token. Use it for a health check or a public price list. |
deny | The gateway always refuses it, even with a valid token. |
Every other call needs a login.
rateLimit and quota: how often
Code
| Setting | Effect |
|---|---|
rateLimit | At most calls calls in every periodSeconds seconds. Extra calls get 429. Use it to protect your API from bursts. |
quota | At most calls calls in every periodDays days. Use it for a monthly allowance. |
cors: which websites may call from a browser
Code
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
Code
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
| Field | Meaning |
|---|---|
source | Folder with your code, relative to the config. Files in its .gitignore and in exclude are not uploaded. |
runtime | nodejs, python or dotnet. |
runtimeVersion | For example NODE_22_LTS. The platform lists the allowed values. |
healthPath | Path the platform probes to check that your API is up. |
exclude | More 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
4. Try it and check it
Run these before you deploy:
Code
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:
Code
| Answer | Meaning |
|---|---|
200 on a public call | The call is open and your API answered. |
401 on a call without a token | The gateway is protecting that call. |
404 | The path is not in your OpenAPI file. |
429 | The rate limit was reached. |
502 or 504 | Your 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.