LLM gateway admin API¶
The LLM gateway is a centralized service that manages access to LLMs from external providers. It offers several key benefits:
- Policy enforcement and granular access of approved LLMs.
- Standardized interactions with multiple LLM providers.
- Security, monitoring, and cost controls across all LLM usage.
- Dynamic model selection for agents, providing access to LLMs in the gateway catalog to support task optimization.
The following endpoints let an organization administrator scope the LLM gateway functionality to their own organization:
- Default credential rule overrides: Sets which credential the gateway uses by default when routing requests to a given provider or model, for each user in the organization.
- Custom LLM catalog entries: Configures self-registered LLMs (for example, a model your organization has direct provider access to) so they appear in your tenant's LLM catalog alongside the DataRobot-managed models.
- Permission rules: Specifies user, group, and organization-level access for a given LLM, LLM family, or provider. "Family" in this API is a synonym for "Publisher" as seen in the UI.
Authentication and access¶
All endpoints on this page require the same Bearer token authentication as the rest of the DataRobot public API (an API key or OAuth token for a DataRobot user):
Authorization: Bearer YOUR_API_TOKEN
The authenticated user must also hold the organization administrator role in their tenant, and must not belong to a trial organization—these endpoints return 403 Forbidden for trial users regardless of role.
There is no request parameter for selecting a tenant or organization. Every operation reads and writes only the caller's own tenant, derived from their authentication. You cannot view or modify another tenant's credential rules or catalog entries through this API.
Base path¶
All paths below are relative to the following base path:
/api/v2/genai/llmgw/admin
Access policy for new entries¶
A catalog entry you create becomes visible in GET /catalog/ and usable in chat completions as soon as it is created, with no separate activation or registration step. Visibility and usability follow the same access policy as every other LLM—evaluation checks for a rule at the LLM level first, then the publisher level, then the provider level—and uses the first level that has one configured. In practice, a new entry automatically inherits whatever provider- or publisher-level policy your organization already has (for example, a "Default allow" on Bedrock), with no extra step required. If your organization has no policy at all for the entry's provider or publisher, and the entry is not a preview LLM, it starts out denied by default until you configure access. This is the same default-deny behavior applied to a new DataRobot-managed LLM.
Permission rules¶
Use the permission rule endpoints to configure provider-, publisher-, or LLM-level policy directly in the gateway for controlling access on a user, group, or organizational level. Rules can be set at any of the three levels; a level with no direct rule of its own falls back to the next level up, as described in Access policy for new entries.
| Verb | Path | Description |
|---|---|---|
GET |
/permissions/ |
Get the tree of providers and families, with the rule (if any) configured directly on each. |
GET |
/permissions/llms/ |
List LLMs, with the rule (if any) configured directly on each. |
POST |
/permissions/ |
Set the allow/deny/remove state of one or more rules. |
DELETE |
/permissions/ |
Delete every rule on one resource. |
Get the permission tree¶
GET /permissions/
Returns every provider your organization can configure permissions for (see Provider values) together with their LLM families. Not paginated—the number of providers and families is small and fixed.
Response—200 OK:
{
"providers": [
{
"name": "Amazon Bedrock",
"slug": "bedrock",
"permissions": {
"orgAllow": true,
"overrides": {
"users": [
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"name": "Ada Lovelace",
"username": "ada@example.com",
"allow": false
}
],
"groups": []
}
},
"families": [
{
"name": "Anthropic",
"slug": "bedrock__anthropic",
"permissions": null,
"modifiedAt": null,
"modifiedBy": null
}
],
"modifiedAt": "2026-08-01T12:00:00Z",
"modifiedBy": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"name": "Ada Lovelace",
"username": "ada@example.com"
}
}
]
}
Provider object
| Field | Type | Description |
|---|---|---|
name |
string | A human-readable provider label (for example, "Amazon Bedrock"). |
slug |
string | A stable identifier for this provider. See Provider values. |
permissions |
object | null | The rule configured directly on this provider, or null if none exists. See Permission object. |
families |
array of object | The provider's LLM families (see below). |
modifiedAt |
string (date-time) | null | The time the direct rule, if any, was last modified. |
modifiedBy |
object | null | The user who last modified it: {"id", "name", "username"}. name/username are null if the user could not be resolved. |
Family object (nested under families)
| Field | Type | Description |
|---|---|---|
name |
string | The family's creator label (for example, "Anthropic"). |
slug |
string | |
permissions |
object | null | The rule configured directly on this family, or null if none exists. |
modifiedAt / modifiedBy |
— | Same as on the provider object. |
Note
Each level of the tree only shows a rule configured directly on it—a rule on a provider is not echoed onto its families, and vice versa. See Access policy for new entries for how access is resolved when a level has no direct rule of its own.
List LLMs with permissions¶
GET /permissions/llms/
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
offset |
integer | 0 |
The number of entries to skip. |
limit |
integer | 500 |
The maximum entries to return (0–500). |
includeRetired |
boolean | false |
Whether to include retired LLMs. |
model |
string | — | Return only the LLM with this exact model string. |
namePart |
string | — | Return only LLMs whose name contains this substring (2–64 characters). |
provider |
string | — | Return only LLMs of this provider. See Provider values. |
family |
string | — | Return only LLMs of this family. Use a family slug from Get the permission tree. |
If both provider and family are given, family must belong to provider.
Response—200 OK, a paginated object in the same shape as Custom LLM catalog entries:
{
"totalCount": 1,
"count": 1,
"next": null,
"previous": null,
"data": [
{
"model": "bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0",
"name": "Claude Sonnet 4.5",
"permissions": null,
"creator": "Anthropic",
"retirementDate": null,
"isDeprecated": false,
"isActive": true,
"modifiedAt": null,
"modifiedBy": null
}
]
}
| Field | Type | Description |
|---|---|---|
model |
string | The LLM's model identifier. |
name |
string | The display name. |
permissions |
object | null | The rule configured directly on this LLM (not inherited from its family or provider). See Permission object. |
creator |
string | The organization that created the model. See Valid provider/creator pairings. |
retirementDate |
string (date) | null | The date the LLM was/will be retired. |
isDeprecated / isActive |
boolean | Computed from retirementDate. |
modifiedAt / modifiedBy |
— | Same as on the provider object. |
Errors
| Status | When |
|---|---|
400 Bad Request |
provider or family is not a recognized slug; provider is datarobot or another non-public provider; or family does not belong to the given provider. |
Note
Non-public providers (DataRobot self-hosted models, and the internal mock test provider) never appear in this listing, even when enabled—they are not access-controlled at runtime.
Update permission rules¶
POST /permissions/
Sets the allow/deny/remove state of one or more (resource, subject) rules in a single request.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
data |
array of object | Yes | 1–100 permission items (see below). |
Each item in data:
| Field | Type | Description |
|---|---|---|
resourceId |
string | The resource to set a rule on. See Resource types for the expected format. |
resourceType |
string | One of llm, family, provider. See Resource types. |
state |
string | One of allow, deny, remove. See Permission states. |
subjectId |
string | The subject the rule applies to. See Subject types. |
subjectType |
string | One of user, group, organization. See Subject types. |
Response—204 No Content.
Errors
| Status | When |
|---|---|
400 Bad Request |
A resourceId/resourceType pair does not resolve to a real LLM, family, or provider; the resource is datarobot or another non-public provider/family; or applying this request would leave more than 100 subjects on a single resource's rule. |
409 Conflict |
Two or more items in the same request target the same resource and subject with different state values. |
500 Internal Server Error |
The upstream access-controls service could not be reached. |
Note
The gateway applies items in batches (removals first, then new rules, then additions to existing rules), and the batches are not transactional—if a later batch fails, earlier batches have already taken effect.
Delete permission rules¶
DELETE /permissions/
Deletes every rule on one resource—both the allow-rule and the deny-rule, for every subject—resetting it to have no direct rule at all. Rules inherited from the resource's parents will then govern the resource, if any exist.
Request body
| Field | Type | Description |
|---|---|---|
resourceId |
string | The resource to clear. See Resource types. |
resourceType |
string | One of llm, family, provider. |
Response—204 No Content. Deleting a resource with no existing rules is a no-op, not an error.
Errors
| Status | When |
|---|---|
400 Bad Request |
resourceId/resourceType does not resolve to a real LLM, family, or provider. |
500 Internal Server Error |
The upstream access-controls service could not be reached. |
Permission object¶
The permissions field on a provider, family, or LLM entry is null when no rule is configured directly on that resource. Otherwise:
{
"orgAllow": true,
"overrides": {
"users": [
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"name": "Ada Lovelace",
"username": "ada@example.com",
"allow": false
}
],
"groups": [
{ "id": "65f1a2b3c4d5e6f7a8b9c0d4", "name": "Engineering", "membersCount": 12, "allow": true }
]
}
}
| Field | Type | Description |
|---|---|---|
orgAllow |
boolean | null | The organization-wide default set via a subjectType: "organization" rule on this resource, or null if none is set. |
overrides.users |
array of object | Per-user overrides: {"id", "name", "username", "allow"}. allow: true grants, allow: false denies, regardless of orgAllow. |
overrides.groups |
array of object | Per-group overrides: {"id", "name", "membersCount", "allow"}. |
If the gateway can no longer resolve a user or group (for example, it was removed, or it belongs to a different tenant), it still appears in overrides, with name (and username, for users) returned as null.
Resource types¶
| Type | ID |
|---|---|
llm |
The LLM's model string (for example, bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0), including one of your own custom catalog entries. |
family |
|
provider |
A provider slug. See Provider values. |
datarobot and mock cannot be used as a provider resource—self-hosted models are not access-controlled through this API, and mock is a test-only provider that skips access evaluation entirely.
Permission states¶
| State | Effect |
|---|---|
allow |
Grants the subject access to this resource, overriding the organization default. |
deny |
Denies the subject access to this resource, overriding the organization default. |
remove |
Clears any direct allow/deny rule for this subject on this resource. The subject then falls back to the organization default, or, for a family or LLM with no direct rule of its own, to the next level up. |
Subject types¶
| Type | ID |
|---|---|
user |
A DataRobot user ID. |
group |
A DataRobot group ID. |
organization |
The organization's ID—sets the resource's organization-wide default (orgAllow) instead of a per-subject override. |
Credential rule overrides¶
A credential rule tells the gateway which stored credential to use, by default, for requests to a given LLM provider (optionally narrowed to one model) from anyone in your tenant. Use this to point the gateway at your organization's own provider credentials instead of DataRobot's shared default pool.
| Verb | Path | Description |
|---|---|---|
GET |
/credentials/ |
List the tenant's default credential rule overrides. |
POST |
/credentials/ |
Add a tenant-scoped default credential rule override. |
DELETE |
/credentials/{credential_id}/ |
Delete a tenant-scoped default credential rule override. |
List credential rule overrides¶
GET /credentials/
Returns every default credential rule configured for the tenant.
Query parameters
| Parameter | Type | Description |
|---|---|---|
llmProvider |
string | Filter to rules for this provider. See Provider values. Mutually exclusive with model. |
model |
string | Filter to rules for this exact model string. Mutually exclusive with llmProvider. |
Passing both llmProvider and model returns 400 Bad Request.
Response—200 OK, a JSON array of credential rule objects.
Create a credential rule override¶
POST /credentials/
Creates a default credential rule for the tenant. You cannot set the scope explicitly—a rule created here always applies to your own tenant.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
credential |
object | Yes | The credential this rule points to. See Credential reference object. |
llmProvider |
string | Yes | The provider this rule applies to. See Provider values. |
model |
string | No | If set, the rule applies to this model only; otherwise it applies to every model under the provider. The string must start with the provider's model prefix (for example, bedrock/... for bedrock)—a mismatched prefix returns 422. |
Response—201 Created, a credential rule object.
Errors
| Status | When |
|---|---|
409 Conflict |
A rule already exists for this tenant, provider, and model combination. |
422 Unprocessable Entity |
model does not match the provider's model prefix. |
Delete a credential rule override¶
DELETE /credentials/{credential_id}/
Deletes one credential rule belonging to the tenant.
Path parameters
| Parameter | Type | Description |
|---|---|---|
credential_id |
string | The rule's id. |
Response—204 No Content.
Errors
| Status | When |
|---|---|
404 Not Found |
No such rule exists or the rule belongs to a different tenant. |
Credential rule object¶
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"scope": {
"scope": "tenant",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
},
"credential": {
"source": "dr_secure_config",
"id": "65f1a2b3c4d5e6f7a8b9c0d2"
},
"llmProvider": "bedrock",
"model": null
}
| Field | Type | Description |
|---|---|---|
id |
string | The rule's identifier. |
scope |
object | Always {"scope": "tenant", "id": "<your tenant id>"} for rules created through this API. |
credential |
object | See Credential reference object. |
llmProvider |
string | The provider this rule applies to. |
model |
string | null | The specific model this rule applies to, or null if it applies to all models from a provider. |
Credential reference object¶
| Field | Type | Description |
|---|---|---|
source |
string | The credential store the id refers to. Must be dr_secure_config. |
id |
string | The identifier of the referenced credential in that store—a Secure Config entry ID. |
Note
The credential itself is created and managed through the existing Secure Config API, not through this endpoint. This API only records which credential the gateway should use as the tenant's default.
Note
The credential's JSON must match the field shape the gateway expects for its provider—see LLM gateway model configuration for the field list and JSON examples per provider.
If every endpoint in the credential's JSON includes "api_type": "azure" (exactly that key, lowercase with an underscore—not apiType), the gateway parses it as an Azure credential regardless of which provider this rule or the tenant entry names. This lets an Azure-backed endpoint serve a tenant entry registered under openai or another OpenAI-compatible provider. Omit api_type unless you need this.
Provider values¶
Valid provider values are: azure, bedrock, vertex_ai, anthropic, cohere, openai, togetherai, cerebras, groq, alibaba, and other.
The special value other circumvents the logic normally used to build a model string for each provider. When using other in a credential rule, the credential JSON must have the following shape, including the field api_base to provide the base URL that should receive requests.:
{
"endpoints": [
{
"region": "global",
"api_base": "<your-base-url>",
"api_key": "<your-api-key>",
}
]
}
Custom LLM catalog entries¶
A catalog entry describes one LLM to make available to your organization; it uses the same shape as DataRobot's own globally available LLMs. Entries you create here are scoped to your tenant only, and never affect or become visible to other organizations.
| Verb | Path | Description |
|---|---|---|
GET |
/llms/ |
List the tenant's LLM catalog entries. |
POST |
/llms/ |
Create a tenant-scoped LLM catalog entry. |
GET |
/llms/{entry_id}/ |
Get one of the tenant's LLM catalog entries. |
PATCH |
/llms/{entry_id}/ |
Update one of the tenant's LLM catalog entries. |
DELETE |
/llms/{entry_id}/ |
Delete one of the tenant's LLM catalog entries. |
List catalog entries¶
GET /llms/
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
offset |
integer | 0 |
The number of entries to skip. |
limit |
integer | 500 |
The maximum entries to return (0–500). |
Response—200 OK, a paginated object:
{
"totalCount": 1,
"count": 1,
"next": null,
"previous": null,
"data": [ /* array of catalog entry objects, see below */ ]
}
Create a catalog entry¶
POST /llms/
Request body
| Field | Type | Required | Description |
|---|---|---|---|
provider |
string | Yes | The LLM provider. See Provider values. |
creator |
string | Yes | The organization that created the model (for example, Anthropic, Meta). The string must form a valid provider/creator pairing—see Valid provider/creator pairings. |
model |
string | Yes | The provider-hosted model identifier. The string must start with the provider's LiteLLM prefix (for example, bedrock/anthropic.claude-...). |
name |
string | Yes | The display name. |
llmId |
string | Yes | Your chosen stable ID for this LLM. |
version |
string | Yes | The model version string. |
description |
string | Yes | The description shown to users. |
license |
string | Yes | The license name. |
supportedLanguages |
array of string | Yes | Currently only Multilingual is a defined value. |
contextSize |
integer | Yes | The context window size, in tokens. Has no effect in the LLM Gateway itself, but other services may read it. |
maxCompletionTokens |
integer | Yes | The maximum tokens the model can generate in one completion. Has no effect in the LLM Gateway itself, but other services may read it. |
inputTypes |
array of string | Yes | Any of text, image. |
outputTypes |
array of string | Yes | Any of text, image. |
documentationLink |
string | Yes | A link to the model's own documentation. |
referenceLinks |
array of object | Yes | [{"name": "...", "url": "..."}]. |
availableLitellmEndpoints |
object | Yes | {"supportsChatCompletions": bool, "supportsResponses": bool}. |
capabilities |
array of string | No | Any of tool_calling, reasoning. |
retirementDate |
string (date) | No | A planned retirement date, if known. |
customModelDeploymentId |
string | No | Set only if this entry routes to a DataRobot custom model deployment rather than a direct provider endpoint. |
suggestedReplacement |
string | No | An llmId to suggest once this entry is retired. |
isMetered |
boolean | No | Opt in to metering this entry's usage against your own resource codes. Defaults to false. If true, resourceCodes must also be set. |
resourceCodes |
array of object | No | Metering tiers: [{"code": "...", "minTokens": int or null, "maxTokens": int or null}]. Bounds are inclusive input-token ranges; a tier with neither bound is unconditional. Every code must start with BYO_. Required if isMetered is true. |
Response—201 Created, a catalog entry object.
Errors
| Status | When |
|---|---|
409 Conflict |
An entry for this model already exists in the tenant. |
422 Unprocessable Entity |
A server-assigned field was included; provider/creator is not a valid pairing; model does not match the provider's prefix; provider is not supported for tenant entries (see note below); or scope names anything other than the tenant. |
Note
provider: datarobot is not currently supported for tenant-created entries and is rejected with 422.
Get a catalog entry¶
GET /llms/{entry_id}/
Response—200 OK, a catalog entry object.
Errors—404 Not Found if the entry does not exist or belongs to another tenant or to the global catalog.
Update a catalog entry¶
PATCH /llms/{entry_id}/
Partial update: send only the fields you want to change, in a plain JSON object (either camelCase or snake_case field names, not a mix of both spellings of the same field in one request).
Request body—any subset of the mutable fields. All other fields listed under Create a catalog entry except provider, creator, and model are mutable; provider, creator, model, llmId, customModelDeploymentId and the identity fields below are immutable—delete and recreate the entry to change any of those.
Response—200 OK, the updated catalog entry object.
Errors
| Status | When |
|---|---|
404 Not Found |
No such entry in the tenant. |
422 Unprocessable Entity |
The patch is empty; a field is unknown, immutable, or server-assigned; or the resulting entry would fail the same validation as creation. |
Delete a catalog entry¶
DELETE /llms/{entry_id}/
Response—204 No Content.
Errors—404 Not Found if no such entry exists in your tenant.
Catalog entry object¶
{
"id": "65f1a2b3c4d5e6f7a8b9c0d3",
"scope": { "scope": "tenant", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" },
"provider": "bedrock",
"creator": "Anthropic",
"model": "bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0",
"llmId": "my-tenant-claude-sonnet",
"name": "Claude Sonnet 4.5 (tenant BYO)",
"version": "2025-09-29",
"description": "Tenant-registered Claude Sonnet 4.5 via our own Bedrock account.",
"license": "See provider terms",
"supportedLanguages": ["Multilingual"],
"contextSize": 200000,
"maxCompletionTokens": 64000,
"inputTypes": ["text", "image"],
"outputTypes": ["text"],
"capabilities": ["tool_calling", "reasoning"],
"documentationLink": "https://...",
"referenceLinks": [],
"dateAdded": "2026-09-09",
"retirementDate": null,
"isPreview": false,
"isMetered": false,
"availableForTrial": false,
"isDeprecated": false,
"isActive": true,
"crossRegionInferenceMap": {},
"availableRegions": [],
"availableLitellmEndpoints": { "supportsChatCompletions": true, "supportsResponses": false },
"unsupportedParams": [],
"resourceCodes": [],
"permissionId": "65f1a2b3c4d5e6f7a8b9c0d3"
}
Fields not covered in Create a catalog entry:
| Field | Type | Description |
|---|---|---|
id |
string | The entry's identifier. |
scope |
object | Always {"scope": "tenant", "id": "<your tenant id>"} for entries created through this API. |
dateAdded |
string (date) | Set by the server at creation time. |
availableForTrial |
boolean | Always false for tenant entries—trial availability is a DataRobot entitlement decision, not a tenant's. |
isDeprecated / isActive |
boolean | Computed from retirementDate. |
availableRegions |
array of string | Has no effect for custom LLM catalog entries. |
unsupportedParams |
array of string | Computed from the model's provider capabilities. |
permissionId |
string | Internal identifier; equal to id for tenant entries. |
isMetered and resourceCodes are yours to set—see Create a catalog entry. Unlike DataRobot-billed catalog entries, your own provider usage is unmetered by default; opting in only gets you usage stats against resource codes you define, not DataRobot billing.
Server-assigned fields¶
The following fields are assigned by the server: id, permissionId, dateAdded, availableForTrial, isDeprecated, isActive, unsupportedParams. Sending any of these in a POST request body is rejected with 422.
Mutable fields¶
Every field on the entry except id, scope, permissionId, provider, creator, model, llmId, and customModelDeploymentId can be changed with PATCH. The excluded fields define what the entry is or routes to. To change them, delete and recreate the entity.
Valid provider/creator pairings¶
| Provider | Valid creator values |
|---|---|
azure |
OpenAI |
bedrock |
Amazon, Anthropic, Cohere, DeepSeek, Meta, Mistral, NVIDIA, OpenAI |
vertex_ai |
Anthropic, Google, Meta, Mistral, OpenAI |
anthropic |
Anthropic |
cohere |
Cohere |
openai |
OpenAI |
togetherai |
Arcee AI, Google, Marin, Meta, Mistral |
alibaba |
Alibaba |
other |
Other |
A provider/creator combination not listed in this table is rejected with 422 Unprocessable Entity. cerebras and groq currently have no valid tenant-entry pairing.
Common error responses¶
| Status | Meaning |
|---|---|
400 Bad Request |
Invalid input on the permission rules endpoints—an unrecognized provider/family/LLM, or a disallowed resource. The detail field describes what and why. |
401 Unauthorized |
Missing or invalid credentials. |
403 Forbidden |
User was authenticated, but does not have organization admin permission, or the organization is a trial org. |
404 Not Found |
The resource does not exist. |
409 Conflict |
A rule or entry already exists for the same uniqueness key (tenant + provider + model), or conflicting items were given in a single permission rules request. |
422 Unprocessable Entity |
The request body failed validation on the credential or catalog entry endpoints; the detail field describes which field and why. |