Create LLM Provider Definition
Endpoint
POST /apiops/projects/{projectName}/llm-provider-definitions/{definitionName}/
Authentication
Requires a Personal API Access Token.
Header
Authorization: Bearer YOUR_TOKEN
Request
Headers
| Header | Value | Required |
|---|---|---|
| Authorization | Bearer {token} | Yes |
| Content-Type | application/json | Yes |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| projectName | string | Yes | Project name |
| definitionName | string | Yes | Provider catalog definition name (must match the effective name in the body) |
Query Parameters
None
Request Body
The body is an LlmProviderDefinition object — unlike Create LLM Provider, this is a plain entity, not a polymorphic type, so no _class discriminator is required or accepted.
Full JSON Body Example
{
"name": "internal-llm-gateway",
"code": "internal-llm-gateway",
"displayName": "Internal LLM Gateway",
"defaultEndpoint": "https://llm-gateway.internal.example.com/v1",
"defaultApiVersion": "v1",
"defaultAuthScheme": "API_KEY_HEADER",
"defaultAuthHeaderName": "x-api-key",
"iconUrl": "https://cdn.example.com/icons/internal-llm.svg",
"docsUrl": "https://wiki.internal.example.com/llm-gateway",
"wireProtocol": "OPENAI_COMPATIBLE",
"defaultChatCompletionPath": "/v1/chat/completions",
"defaultEmbeddingPath": "/v1/embeddings",
"supportsEmbedding": true,
"supportsResponses": false
}
Request Body Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| name | string | No | code value, then path value | Definition name; if blank, falls back to code, then to definitionName. Must match definitionName in the path (case-insensitive) once resolved |
| code | string | No | - | Provider type code (e.g. internal-llm-gateway); used as the name fallback when name is blank |
| displayName | string | No | - | UI label |
| defaultEndpoint | string | No | - | Default base API URL |
| defaultApiVersion | string | No | - | Default API version |
| defaultAuthScheme | string | No | - | Default auth scheme enum constant (BEARER, API_KEY_HEADER, BASIC, AWS_SIGV4, OAUTH2, NONE, CUSTOM) |
| defaultAuthHeaderName | string | No | - | Default credential header name |
| iconUrl | string | No | - | Provider icon URL |
| docsUrl | string | No | - | Vendor documentation deep link |
| wireProtocol | string | No | null | Adapter family this provider's wire format resolves against — one of OPENAI_COMPATIBLE, ANTHROPIC, GEMINI, BEDROCK, VLLM. Not validated server-side, but see the note below — a code that doesn't match a built-in provider type has nothing to fall back to when this is left blank |
| defaultChatCompletionPath | string | No | null | Default chat-completion endpoint path (e.g. /chat/completions, /messages) |
| defaultEmbeddingPath | string | No | null | Default embedding endpoint path |
| defaultAudioTranscriptionPath | string | No | null | Default speech-to-text endpoint path |
| defaultAudioSpeechPath | string | No | null | Default text-to-speech endpoint path |
| defaultImageGenerationPath | string | No | null | Default image-generation endpoint path |
| defaultResponsesPath | string | No | null | Default OpenAI Responses API-style endpoint path |
| supportsEmbedding | boolean | No | null | Whether this provider has an embedding endpoint |
| supportsResponses | boolean | No | null | Whether this provider supports the Responses-style endpoint |
| builtIn | boolean | No | forced false | Ignored on write and always persisted as false. Sending "builtIn": true is rejected outright (see below) |
| id, projectId, lastUpdatedAt | — | No | server-assigned | Any value sent for these fields is ignored — id/projectId are resolved server-side (upsert lookup / path project), lastUpdatedAt is always set to the current time |
Notes
namemust matchdefinitionNamein the path (case-insensitive) once resolved (name→code→ path fallback), otherwise a400 Bad Requestis returned- Sending
"builtIn": truein the body is rejected with a400 Bad Request("Built-in provider definitions are read-only."), regardless of whether a definition with that name already exists - No
_classdiscriminator — this is a plain entity body, not a polymorphicConnectionConfigsubtype wireProtocol/defaultChatCompletionPathand the other path/capability fields are not required by this endpoint the way they are on the Manager UI's own create form. Ifcodematches a built-in provider type, a value left blank here still resolves through that type's own default at request time. Ifcodedoes not match any built-in provider type — a genuinely custom provider — a blankwireProtocolordefaultChatCompletionPathhas no fallback to resolve through and behaves as unset at request time; fill them in explicitly for a custom provider created through this endpoint. See Provider Type Catalog for the full resolution order.- On the upsert branch (a definition with this
namealready exists and is custom), the incoming body replaces the full row rather than merging into it — a field omitted from the request is saved asnull, not left at its previous value. Re-send every field you want to keep, includingwireProtocoland the path/capability fields.
Response
Success Response (200 OK)
{
"status": "SUCCESS",
"deploymentResult": {
"success": true
}
}
EnumStatus
SUCCESS- Operation successfulFAILURE- Operation failed
Error Response (400 Bad Request)
{
"status": "FAILURE",
"resultMessage": "Built-in provider definitions are read-only."
}
or
{
"status": "FAILURE",
"resultMessage": "Provider definition name in path (internal-llm-gateway) does not match name in body (other-name)!"
}
or
{
"status": "FAILURE",
"resultMessage": "Provider definition body can not be empty!"
}
Error Response (401 Unauthorized)
{
"status": "FAILURE",
"resultMessage": "Token is not valid!"
}
cURL Example
curl -X POST \
"https://demo.apinizer.com/apiops/projects/MyProject/llm-provider-definitions/internal-llm-gateway/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "internal-llm-gateway",
"code": "internal-llm-gateway",
"displayName": "Internal LLM Gateway",
"defaultEndpoint": "https://llm-gateway.internal.example.com/v1",
"defaultApiVersion": "v1",
"defaultAuthScheme": "API_KEY_HEADER",
"defaultAuthHeaderName": "x-api-key"
}'
Permissions
- User must have
AI_DEVELOPMENT+MANAGEpermission in the project
Notes and Warnings
- Upsert Semantics:
- If a definition with the same
namealready exists in the caller's visible scope (built-in ∪ this project's custom entries) and is not built-in, it is updated (its internal ID is reused) - Otherwise a new definition is created, owned by the calling project
- If a definition with the same
- Built-in Is Read-Only:
- Both the target of an update (an already-built-in row) and the incoming body (
"builtIn": true) are checked — either one is rejected with the same stable message
- Both the target of an update (an already-built-in row) and the incoming body (
- No
_classDiscriminator:- Unlike
ConnectionConfigLlm(LLM Provider) bodies, this entity is not polymorphic
- Unlike
- No Secrets, No Deploy:
- The entity carries no credential fields, and creating a definition never triggers an AI Gateway worker deploy —
deploymentResultreflects the database write only
- The entity carries no credential fields, and creating a definition never triggers an AI Gateway worker deploy —
Related Documentation
- Update LLM Provider Definition - Update an existing custom definition
- Get LLM Provider Definition - Retrieve a definition by name
- List LLM Provider Definitions - List all definitions visible to a project
- LLM Provider Definitions API - Resource overview, permissions and the LlmProviderDefinition vs. LLM Provider distinction