> ## Documentation Index
> Fetch the complete documentation index at: https://docs.airctrl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# AI gateways

> Configure AI providers, gateways, tokens, routing, limits and observability.

export function AirctrlWordmark() {
  return <span className="airctrl-wordmark" aria-label="AIRCTRL">
      <span aria-hidden="true" className="airctrl-wordmark-air">AIR</span>
      <span aria-hidden="true" className="airctrl-wordmark-ctrl">CTRL</span>
    </span>;
}

An <AirctrlWordmark /> gateway routes AI requests through provider credentials stored in <AirctrlWordmark />. Applications use a gateway token instead of receiving the provider credential.

## The complete flow

1. Choose an AI provider.
2. Add a provider credential.
3. Create a gateway in a project.
4. Attach the credential and choose routing defaults.
5. Create a gateway token.
6. Point your provider client at the returned data-plane URL.
7. Inspect logs, usage and key access.

## List providers

```ts theme={}
const providers = await airctrl.listProviders()
const openai = providers.find((provider) => provider.slug === 'openai')
if (!openai) throw new Error('OpenAI is not enabled for this AIRCTRL deployment')
```

```bash theme={}
airctrl gateway providers
```

MCP request:

```text theme={}
Show the AI providers currently enabled in AIRCTRL. Include each provider's
name and ID. Do not add a credential or change any gateway.
```

<div className="technical-reference">
  **MCP tool used:** `list_providers`
</div>

## Add a provider credential

The credential value is accepted for validation and encrypted storage. It is never returned by list or read operations.

SDK:

```ts theme={}
const credential = await airctrl.createProviderCredential({
  accountId: '00000000-0000-4000-8000-000000000001',
  providerId: openai.provider_id,
  label: 'Production OpenAI',
  apiKey: process.env.OPENAI_API_KEY!,
})
```

CLI reads the provider value from an environment variable named by the flag:

```bash theme={}
airctrl gateway provider-credential-create \
  --account 00000000-0000-4000-8000-000000000001 \
  --provider 00000000-0000-4000-8000-000000000070 \
  --label "Production OpenAI" \
  --api-key-env OPENAI_API_KEY
```

Put the value in an `AIRCTRL_MCP_KEY_*` environment variable and pass only that variable's name.

```text theme={}
Add an OpenAI provider credential named "Production OpenAI" to account
"00000000-0000-4000-8000-000000000001". Read the provider key from
"AIRCTRL_MCP_KEY_OPENAI_PRODUCTION". Show only the variable name and safe
credential details, then wait for my confirmation. Never print the key.
```

<div className="technical-reference">
  **MCP tool used:** `add_provider_key`
</div>

## Create a gateway

```ts theme={}
const gateway = await airctrl.createGateway({
  accountId: '00000000-0000-4000-8000-000000000001',
  projectId: '00000000-0000-4000-8000-000000000010',
  name: 'Payments AI',
  slug: 'payments-ai',
  defaultProviderId: openai.provider_id,
  defaultModel: 'gpt-5',
  credentialBindings: [{
    credentialId: credential.credential_id,
    modelId: 'gpt-5',
  }],
})
```

```bash theme={}
airctrl gateway create \
  --account 00000000-0000-4000-8000-000000000001 \
  --project 00000000-0000-4000-8000-000000000010 \
  --name "Payments AI" \
  --slug payments-ai \
  --provider 00000000-0000-4000-8000-000000000070 \
  --model gpt-5 \
  --credential 00000000-0000-4000-8000-000000000200
```

MCP uses `create_gateway` for a bare gateway. Use `setup_gateway` when the same operation must validate a provider key, bind one live-catalog model, create the gateway, mint a token, and return connection information.

```text theme={}
Create a bare AIRCTRL gateway named "Payments AI" in project
"00000000-0000-4000-8000-000000000010" under account
"00000000-0000-4000-8000-000000000001". Do not attach a provider key yet.
Show the proposed gateway details and wait for my confirmation before creating it.
```

<div className="technical-reference">
  **MCP tool used:** `create_gateway`
</div>

## Create a gateway token

<div className="section-help">
  Gateway token plaintext is returned once.

  CLI command: `gateway token-create`

  Store the returned value before leaving the response. Listing tokens later returns metadata only.
</div>

```ts theme={}
const token = await airctrl.createGatewayToken(
  gateway.gateway_id,
  {
    name: 'Payments production',
    scopes: ['run'],
    allowedModels: ['gpt-5'],
    spendLimit: 100,
    spendWindow: 'monthly',
    rateLimitPerMin: 60,
  },
  { accountId: '00000000-0000-4000-8000-000000000001' },
)
```

MCP request:

```text theme={}
Create a gateway token named "Payments production" for gateway
"00000000-0000-4000-8000-000000000030" in account
"00000000-0000-4000-8000-000000000001". Make it expire in 30 days. Show the
safe request details and wait for my confirmation. Return the token value only
once and only to the approved storage step.
```

<div className="technical-reference">
  **MCP tool used:** `create_gateway_token`
</div>

## Connect an AI client

Use the gateway token with the URLs returned by `get_connection_config` or `setup_gateway`.

* OpenAI-compatible SDKs use the `/compat` base URL.
* OpenAI-native requests use the `/openai/v1` path.
* Anthropic clients use the `/anthropic` base URL.
* Gemini-compatible clients use the returned Gemini endpoint.

The data plane speaks each provider's normal protocol. It is not wrapped in separate <AirctrlWordmark /> SDK methods.

MCP request:

```text theme={}
Show the connection settings for gateway
"00000000-0000-4000-8000-000000000030". Include compatible base URLs and
required header names. Do not create or reveal a token.
```

<div className="technical-reference">
  **MCP tool used:** `get_connection_config`
</div>

## Routing and settings

Use `updateGateway`, `updateGatewaySettings`, `attachGatewayCredential`, and `detachGatewayCredential` in the SDK.

Gateway settings can control:

* Spend limit and period.
* Requests per minute.
* Request logging and optional body logging.
* Allowed models.
* Guardrail mode.
* Cache state and lifetime.

CLI commands: `gateway update`, `settings`, `credential-attach`, and `credential-detach`.

```text theme={}
Review gateway "00000000-0000-4000-8000-000000000030". Propose a monthly
spend limit of 100 and a rate limit of 120 requests per minute. Show the exact
changes and wait for my confirmation. Do not change routing or credentials.
```

<div className="technical-reference">
  **MCP tool used:** `set_gateway_settings`
</div>

## Logs and usage

* Gateway logs show requests for one gateway.
* Project usage combines gateways in one project.
* Key access shows whether <AirctrlWordmark /> granted, denied, or failed to retrieve a provider credential.
* Log-body reads require `usage:read-bodies` because prompts and responses can contain sensitive data.
* Spend reads require `usage:read-spend`.

SDK methods include `listGatewayLogs`, `getGatewayLogDetail`, `listGatewayKeyAccess`, `listUsageLogs`, `getUsageLogDetail`, `getUsageSpend`, and `getUsageMetrics`.

## OpenTelemetry

Use `getGatewayOtelExport` and `updateGatewayOtelExport` to configure metrics and traces. Stored header values are write-only and are never returned.

CLI commands: `gateway otel`, `gateway otel-update`

```text theme={}
Show the current OpenTelemetry export settings for gateway
"00000000-0000-4000-8000-000000000030" in account
"00000000-0000-4000-8000-000000000001". Return only safe settings and never
request stored header values. Do not change anything.
```

<div className="technical-reference">
  **MCP tool used:** `get_otel_export`
</div>

## Common failures

* `403 plan_limit_reached`: the account plan cannot create another gateway.
* `404 gateway_not_found`: the gateway is unavailable in the active account.
* `400`: a provider credential belongs to another account or a setting is invalid.
* `429`: API rate limit, gateway rate limit, or spend limit. Read the error code before retrying.
