# Authenticate callers on a Transit Point

> Let an agent that can't carry the transit token, such as a cloud-hosted agent, call a Transit Point with an API key or a JWT of its own, and refuse every other caller.

This guide turns off the transit token on a Transit Point and has its callers authenticate with an API key or a JWT of their own.

A Transit Point is the outbound route your managed agent calls so the gateway can apply policy and add credentials on the way to an external service. By default it accepts only calls that carry the transit token, which the gateway gives the managed agent with each request it forwards through the surface’s Access Point. For background, see [Surface routing model](/products/affinidi-trust-fabric/agent-gateway/concepts/surface-routing-model.md#the-transit-token).

An agent that the gateway doesn’t call through the Access Point receives no transit token, so every call it makes to the Transit Point, other than a discovery read, is refused with 401. Caller authentication on the Transit Point gives that agent a credential of its own, and the gateway refuses any call without a valid one before anything else runs.

Use this guide when:

- A managed agent hosted by a cloud provider, or another service outside your control, calls the Transit Point directly.

- The agent can send a fixed HTTP header, such as an API key or a bearer token, but can’t pass on a per-request transit token.

- You want a policy on the Transit Point to tell its callers apart by name.

Skip this guide when your managed agent receives its requests through the surface’s Access Point and passes on the X-Transit-Token header. Keep Require transit token on for that agent.

## Prerequisites

- You are logged in to the Agent Gateway dashboard with permission to create and edit surfaces.

- A surface with a Transit Point. To add one, follow [Apply policy to outbound calls](/products/affinidi-trust-fabric/agent-gateway/how-to-guides/policies/apply-policy-to-outbound-calls.md).

- The credential for the method you choose:

- API key (secret store): a secret on the Secrets page whose Secret Type is ApiKey and whose value holds the keys you accept. The API key secret picker lists ApiKey secrets and secrets with no type. See [Secrets](/products/affinidi-trust-fabric/agent-gateway/reference/authentication/secrets.md).

- API key (provider): one key per caller, issued for this surface on the API Keys tab of the Secrets page. See [API keys](/products/affinidi-trust-fabric/agent-gateway/reference/authentication/api-keys.md).

- JWT bearer: a JWT verification strategy for the identity provider that issues your callers’ tokens, and an audience that only this Transit Point accepts. See [Validate bearer tokens on a surface](/products/affinidi-trust-fabric/agent-gateway/how-to-guides/access/validate-bearer-tokens-on-a-surface.md).

- curl, to send the test requests.

Secret hygiene

Store each API key or client secret only in the calling agent’s secrets manager and inject it at runtime. Keep it out of source code, surface configuration and logs. To rotate a key, rotate it on the API Keys tab or update the secret’s value on the Secrets page, then update the agent.

## Steps

Open the Transit Point

- Open Surfaces in the dashboard and open the surface.

- Select the Transit Point node on the canvas to open its config panel.

- Copy the URL from the Listener URL banner. The caller sends its requests to this URL, and the tests below use it as <TRANSIT_POINT_URL>.

Turn off the transit token

In the Who can call this Transit Point section, turn off Require transit token.

The section shows “This Transit Point would serve anyone who can reach it. Keep the transit token on, choose how callers authenticate, or mark it open to any caller.” The message clears when you choose a method in the next step.

Choose how callers authenticate

In Caller authentication, select one method and fill in its fields.

- API key (secret store): set Header callers send the key in, which defaults to X-API-Key. In API key secret, select the secret that holds the accepted keys. Every key in that secret is accepted as one caller.

- API key (provider): set Header callers send the key in, which defaults to X-API-Key. The Transit Point accepts this surface’s API keys, and each key is one caller. An Access Point on the same surface that uses the API Key Provider accepts the same keys, so its callers can call this Transit Point too. To accept a separate set of callers, use API key (secret store).

- JWT bearer: select the JWT verification strategy that checks your callers’ tokens. In Accepted audiences, type the audience reserved for this Transit Point and select Add. Token header defaults to Authorization and Scheme to Bearer.

For JWT bearer, give the Transit Point an audience of its own, such as its Listener URL. A token issued for the Access Point with an audience the Transit Point also accepts would be accepted here too.

Save the surface

Select the save icon (tooltip: Save changes) on the canvas, or press Cmd+S (macOS) / Ctrl+S (Windows/Linux). If the gateway refuses the save, the section shows “The gateway refused the last save:” followed by the reason.

Give the caller its credential

Configure the calling agent to send its credential with every request to <TRANSIT_POINT_URL>:

- API key methods: the key, in the header you named.

- JWT bearer: a token from your identity provider whose aud claim names the audience you added, as Authorization: Bearer <TOKEN> unless you changed Token header or Scheme.

The gateway removes the credential’s header before it forwards the request, so the caller’s key or token stays at the gateway. To authenticate the gateway to the target, use Target Authentication on the same panel.

Give each caller its own rate limit

With API key (provider) or JWT bearer, the Transit Point can tell its callers apart, so you can stop one caller from using up the others’ allowance. Drop a Rate Limit element on the Transit Point and fill in its Per caller (optional) section. See [Networking elements: Per caller](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/networking.md#per-caller-optional).

## Confirm

Replace <TRANSIT_POINT_URL> with the Listener URL you copied. The commands use an API key in X-API-Key. For JWT bearer, replace that header with -H "Authorization: Bearer <TOKEN>".

### Test 1: request with a valid credential returns the target’s response

curl -X POST "<TRANSIT_POINT_URL>" \
  -H 'X-API-Key: <API_KEY>' \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

curl -X POST "<TRANSIT_POINT_URL>" \
  -H 'X-API-Key: <API_KEY>' \
  -H "Content-Type: application/json" \
  -H "A2A-Version: 0.3" \
  -d '{"jsonrpc":"2.0","method":"message/send","id":1,"params":{"message":{"messageId":"test-1","role":"user","parts":[{"kind":"text","text":"Hello"}]}}}'

Expected: the target’s own response, such as 200 OK with its result.

### Test 2: request without a credential returns 401

Send the same request without the X-API-Key header.

Expected: 401.

- 
MCP Transit Point: a JSON-RPC error with code -32001:

```json
{"jsonrpc":"2.0","id":null,"error":{"code":-32001,"message":"Caller credential missing or invalid"}}
```

- 
Other Transit Points: a problem JSON body whose detail is Caller credential missing or invalid.

### Test 3: request from a caller the policy doesn’t name returns 403

This test applies to API key (provider) and JWT bearer, where each caller has a name of its own. The policy reads the caller from input.transit.client, which holds the caller the Transit Point verified: its subject is the value of the JWT verification strategy’s Caller identity claim (sub unless the strategy names another claim), or the API key’s Key ID.

- 
Drop a Policy element on the Managed Agent → Transit Point edge and select a policy definition with this rule, using your callers’ names:

```rego
package surface.policy

default allow := false

named_callers := {"crm-agent", "billing-agent"}

allow if {
    input.transit.client.verification == "source_auth"
    named_callers[input.transit.client.subject]
}
```

- 
Save the surface.

- 
Repeat Test 1 with the credential of a caller that is not in named_callers.

Expected: 403 with Request blocked by surface policy. A caller in named_callers still gets the target’s response. See [OPA policies reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/opa-policies.md#inputtransit) for every input.transit field.

## Troubleshooting

| Symptom | Likely cause | Fix |
| Saving is refused with “This Transit Point would serve anyone who can reach it…”. | Require transit token is off and Caller authentication is None. | Choose a Caller authentication method, or turn the transit token back on. |
| Saving is refused with “Name the audience this Transit Point accepts…”. | JWT bearer has no audience in Accepted audiences. | Type the Transit Point’s audience and select Add. |
| Saving is refused with “Choose the secret that holds the accepted API keys.” | API key (secret store) has no secret selected. | Select the secret in API key secret. |
| 401 with Caller credential missing or invalid although the caller sends a credential. | The header name differs from Header callers send the key in or Token header, the key is not in the secret or was revoked, or the token’s issuer, signature, expiry or audience fails the check. | Match the header name, check the key on the Secrets page, and request a token whose aud names an audience in Accepted audiences. |
| 401 with Transit token missing or invalid. | Require transit token is still on. | Turn it off in Who can call this Transit Point and save the surface. |
| 503 with This Transit Point is unavailable. | The gateway can’t run the Transit Point’s caller authentication, for example because its secret or JWT verification strategy no longer exists, or the Transit Point was stored before version 1.0.4 with no way to authenticate callers. | Select an existing secret or strategy, or choose a method, and save the surface. |
| Callers of the Access Point can also call the Transit Point. | Caller authentication is API key (provider), which accepts the same keys as the Access Point, or a JWT bearer audience is one the Access Point also accepts. | Use API key (secret store) with a separate secret, or give the Transit Point an audience of its own. |
| A Transit Point with a delegated credential returns 403. | Without a transit token, the agent identity comes only from an Identity element on the Managed Agent → Transit Point edge. | Add that Identity element. See [Requirements for a Transit Point with delegated credentials](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/transit-points.md#requirements-for-a-transit-point-with-delegated-credentials). |

## Last resort: open the Transit Point to any caller

When no caller can carry the transit token or a credential, you can mark the Transit Point Open to any caller. It then serves anyone who reaches its address, with no check on who they are, and uses this gateway and any credential it sends to its target on their behalf. Open a Transit Point only when it sends no credential to its target, or only callers you trust can reach its address.

- In Who can call this Transit Point, turn off Require transit token and set Caller authentication to None.

- Turn on Open to any caller. In the dialog Open this Transit Point to any caller?, select Open to any caller.

- Save the surface.

The section then shows a warning that anyone who can reach the Transit Point can call it through this gateway. When its listener URL is reachable from other hosts, it also shows “Transit Point ‘<alias>’ serves callers it does not authenticate and is reachable from other hosts”, followed by the URL. To close it again, turn off Open to any caller and choose a Caller authentication method.

## Next steps

- [Apply policy to outbound calls](/products/affinidi-trust-fabric/agent-gateway/how-to-guides/policies/apply-policy-to-outbound-calls.md): add policy, rate limits and target authentication to the Transit Point.

- [Surface routing model](/products/affinidi-trust-fabric/agent-gateway/concepts/surface-routing-model.md): how the transit token links the Access Point and Transit Points.

## Related

- [Transit Points](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/transit-points.md#who-can-call-this-transit-point): every field in Who can call this Transit Point and the refusals a Transit Point returns.

- [OPA policies reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/opa-policies.md#inputtransit): the input.transit.caller and input.transit.client fields.

- [JWT Verification Strategies](/products/affinidi-trust-fabric/agent-gateway/reference/authentication/jwt-verification-strategies.md): the checks a strategy runs on every token.

- [API keys](/products/affinidi-trust-fabric/agent-gateway/reference/authentication/api-keys.md): issuing, revoking and rotating the keys API key (provider) accepts.

- [Secrets](/products/affinidi-trust-fabric/agent-gateway/reference/authentication/secrets.md): creating the secret API key (secret store) reads.
