Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.baseten.co/llms.txt

Use this file to discover all available pages before exploring further.

In Frontier Gateway, every API key belongs to a group: the resource that owns one billable entity’s external identifier, model set, rate and usage limits, and place in your organizational hierarchy. You manage groups with POST/GET/PATCH/DELETE /v1/gateway/groups[...] and mint, list, or revoke their keys with POST/GET/DELETE /v1/gateway/groups/{group_id}/api_keys[...]. This page walks the full lifecycle: creating a group, building a hierarchy, minting a key, listing and revoking keys, and deleting a group.

Concepts

A group is one node in your hierarchy. The group owns:
  • A metadata.external_entity_id: a stable identifier you choose, unique within your workspace. Use it to map the group back to your own system. The same value is included as externalCustomerId on every billing webhook event for the group’s keys.
  • A metadata.name: an optional human-readable display name.
  • A model set (models[]): the slugs the group is allowed to call, each with optional rate and usage limits.
  • A hierarchy block: a limit_enforcement mode (one of INDEPENDENT or CASCADING) and an optional parent_group_id. Both fields are immutable after creation.
A federated API key is a credential bound to one group. Keys are minted under the group; rotating credentials for a customer means revoking and reissuing the key without touching the group. Each key has a prefix (the substring before the . in the full key string) used as the path parameter in every per-key URL. The plaintext secret after the . is shown once at creation and is never retrievable; lose it and you must revoke and reissue. A key’s model access and limits are derived entirely from its group’s effective config; keys don’t carry per-key overrides. To see how limits compose across a hierarchy, see Rate and usage limits.

Create a group

Create a group with POST /v1/gateway/groups. The body specifies the group’s metadata, its complete model configuration, and a hierarchy block declaring the inheritance mode and an optional parent. The models list defines the group’s complete model set with set semantics. Slugs added to the list are added to the group, and slugs absent from the list on a later update are removed (cascading to existing keys’ access).
curl --request POST \
  --url https://api.baseten.co/v1/gateway/groups \
  --header "Authorization: Api-Key $BASETEN_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "metadata": {
      "name": "Acme prod",
      "external_entity_id": "cust_42"
    },
    "models": [
      {
        "slug": "your-org/your-model",
        "rate_limits": [
          { "type": "TOKEN", "unit": "MINUTE", "threshold": 1000000 },
          { "type": "REQUEST", "unit": "MINUTE", "threshold": 100 }
        ],
        "usage_limits": [
          { "type": "TOKEN", "unit": "DAY", "threshold": 10000000 }
        ]
      }
    ],
    "hierarchy": {
      "limit_enforcement": "INDEPENDENT",
      "parent_group_id": null
    }
  }'
The response is the new group. Save the id. It’s the path parameter for every per-group operation that follows.
{
  "id": "abc123hash",
  "metadata": {
    "name": "Acme prod",
    "external_entity_id": "cust_42"
  },
  "models": [
    {
      "slug": "your-org/your-model",
      "rate_limits": [
        { "type": "TOKEN", "unit": "MINUTE", "threshold": 1000000 },
        { "type": "REQUEST", "unit": "MINUTE", "threshold": 100 }
      ],
      "usage_limits": [
        { "type": "TOKEN", "unit": "DAY", "threshold": 10000000 }
      ]
    }
  ],
  "effective_models": [
    {
      "slug": "your-org/your-model",
      "rate_limits": [
        { "type": "TOKEN", "unit": "MINUTE", "threshold": 1000000, "source_group": "abc123hash" },
        { "type": "REQUEST", "unit": "MINUTE", "threshold": 100, "source_group": "abc123hash" }
      ],
      "usage_limits": [
        { "type": "TOKEN", "unit": "DAY", "threshold": 10000000, "source_group": "abc123hash" }
      ]
    }
  ],
  "hierarchy": {
    "limit_enforcement": "INDEPENDENT",
    "parent_group_id": null
  },
  "created_at": "2026-05-13T12:00:00Z"
}
The models list must be non-empty on create. To clear models from an existing group later, send "models": [] on PATCH; to remove the group entirely, see Delete a group. For the limit-shape reference, see Rate and usage limits.

Build a hierarchy

To nest a group under an existing one, pass the parent’s id as hierarchy.parent_group_id. The child’s limit_enforcement mode must match the root of its subtree. Pick the mode when you create the root, then every descendant uses the same mode.
curl --request POST \
  --url https://api.baseten.co/v1/gateway/groups \
  --header "Authorization: Api-Key $BASETEN_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "metadata": {
      "name": "Acme prod / engineering",
      "external_entity_id": "cust_42_engineering"
    },
    "models": [
      {
        "slug": "your-org/your-model",
        "rate_limits": [
          { "type": "TOKEN", "unit": "MINUTE", "threshold": 700000 }
        ]
      }
    ],
    "hierarchy": {
      "limit_enforcement": "INDEPENDENT",
      "parent_group_id": "abc123hash"
    }
  }'
The child group’s response includes the same models it was configured with, plus an effective_models block showing the limits the runtime enforces after walking up the tree. Each limit in effective_models carries a source_group field pointing to the ancestor (or self) that the limit was anchored to. For a worked example, see Effective limits and inheritance.

List groups

Fetch groups in your workspace with GET /v1/gateway/groups. Results are cursor-paginated. Pass ?external_entity_id= to look up a single group by its external identifier.
curl --request GET \
  --url https://api.baseten.co/v1/gateway/groups \
  --header "Authorization: Api-Key $BASETEN_API_KEY"
The response includes a pagination block with has_more and a cursor you pass back to fetch the next page:
{
  "items": [
    {
      "id": "abc123hash",
      "metadata": { "name": "Acme prod", "external_entity_id": "cust_42" },
      "models": [ /* ... */ ],
      "effective_models": [ /* ... */ ],
      "hierarchy": { "limit_enforcement": "INDEPENDENT", "parent_group_id": null },
      "created_at": "2026-05-13T12:00:00Z"
    }
  ],
  "pagination": {
    "has_more": true,
    "cursor": "aVd2Yk54T2d2V0dFWE13R1l4R2k5UVE="
  }
}
To fetch the next page, pass the previous response’s cursor:
curl --request GET \
  --url "https://api.baseten.co/v1/gateway/groups?cursor=aVd2Yk54T2d2V0dFWE13R1l4R2k5UVE=" \
  --header "Authorization: Api-Key $BASETEN_API_KEY"
You’ve drained the result set when the response has "has_more": false and "cursor": null.

Update a group

Update a group’s mutable fields with PATCH /v1/gateway/groups/{group_id}. You can change metadata.name and the models configuration; the hierarchy block (parent and enforcement mode) is immutable after creation. At least one of metadata.name or models must be provided. Replacing models follows the same set semantics as create: every slug currently on the group but absent from the new list is removed (cascading to existing keys’ access), and new slugs are added. If the group sits in a cascading hierarchy, the new models block is validated against both the group’s ancestors and its descendants. A PATCH that would raise the group above an ancestor’s threshold, or lower the group below a descendant’s threshold, is rejected with 400 Bad Request: "Child group exceeds parent group limit.". See Cascading mode for the full ordering rules.
curl --request PATCH \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash \
  --header "Authorization: Api-Key $BASETEN_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "models": [
      {
        "slug": "your-org/your-model",
        "rate_limits": [
          { "type": "TOKEN", "unit": "MINUTE", "threshold": 1500000 }
        ]
      }
    ]
  }'
The response is the updated group, with refreshed effective_models reflecting the new limits and any downstream inheritance.

Mint an API key

Mint a new API key for an existing group with POST /v1/gateway/groups/{group_id}/api_keys. The path parameter is the group’s internal id (not its external_entity_id). The body has a single optional name field: a display label for the key. Keys inherit the group’s effective model set and limits; you can’t restrict a key to a subset of the group’s slugs or attach per-key limits.
curl --request POST \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash/api_keys \
  --header "Authorization: Api-Key $BASETEN_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "prod-key-1"
  }'
The response contains the plaintext key, returned exactly once:
{
  "api_key": "aBcDeFg.<api-key-secret>",
  "prefix": "aBcDeFg",
  "name": "prod-key-1"
}
This is the only time the key is returned in plaintext. Save it now: Baseten doesn’t store the secret portion and can’t show it to you again. If you lose it, revoke the key and mint a new one.
To rotate a customer’s credentials without changing their access or limits, mint a new key under the same group, hand the new key to the customer, then revoke the old one once they’ve cut over.

List a group’s keys

Fetch the keys belonging to a group with GET /v1/gateway/groups/{group_id}/api_keys. Results are cursor-paginated with the same shape as the group list.
curl --request GET \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash/api_keys \
  --header "Authorization: Api-Key $BASETEN_API_KEY"
{
  "items": [
    {
      "prefix": "aBcDeFg",
      "name": "prod-key-1"
    }
  ],
  "pagination": {
    "has_more": false,
    "cursor": null
  }
}
Per-key responses carry only the prefix and name. To inspect the model access and limits the key resolves to, fetch its group and read the effective_models block. To fetch a single key by prefix, use GET /v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}:
curl --request GET \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash/api_keys/aBcDeFg \
  --header "Authorization: Api-Key $BASETEN_API_KEY"

Revoke a key

Revoke a single key with DELETE /v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}. Other keys under the same group are unaffected.
curl --request DELETE \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash/api_keys/aBcDeFg \
  --header "Authorization: Api-Key $BASETEN_API_KEY"
{
  "prefix": "aBcDeFg"
}
Revocation is irreversible. After this call, the key can’t authenticate any request and can’t be restored. To restore access for the same downstream customer, mint a new key under the same group.

Delete a group

When a downstream customer churns, delete their group with DELETE /v1/gateway/groups/{group_id}. The call removes the group, revokes every API key in the group, and recursively removes every descendant group and their keys. The external_entity_id is freed for reuse; you can call POST /v1/gateway/groups again with the same value to provision a fresh group.
curl --request DELETE \
  --url https://api.baseten.co/v1/gateway/groups/abc123hash \
  --header "Authorization: Api-Key $BASETEN_API_KEY"
{
  "id": "abc123hash",
  "metadata": {
    "name": "Acme prod",
    "external_entity_id": "cust_42"
  },
  "deleted_at": "2026-05-13T12:34:56Z"
}
To revoke a single key without churning the whole group, use Revoke a key instead.

Next steps