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

# Create Client Model

> Register a client model that holds your provider credentials and return the created record with status 201. The organisation is taken from your authenticated API key, never the request body. The `api_key`, `vertex_credentials`, and `aws_credentials` fields are write-only: stored encrypted and never echoed back.



## OpenAPI

````yaml /api-reference/agents/shared-resources.oas.yaml post /v1/agents/client-models
openapi: 3.1.0
info:
  title: SLNG Agent Resources API
  version: 1.0.0
  description: >-
    Public control-plane API for agent resources: tools, MCP servers, Vault
    secrets and variables, and client models.
servers:
  - url: https://api.agents.slng.ai
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Tools
    description: Create, test, publish, version, and attach agent tools.
    x-page-icon: wrench
  - name: MCP servers
    description: Configure MCP servers and refresh their live capabilities.
    x-page-icon: plug
  - name: Vault
    description: >-
      Store organisation secrets and readable variables without exposing secret
      values.
    x-page-icon: key
  - name: Client models
    description: Manage bring-your-own LLM provider credentials.
    x-page-icon: brain
paths:
  /v1/agents/client-models:
    post:
      tags:
        - Client models
      summary: Create Client Model
      description: >-
        Register a client model that holds your provider credentials and return
        the created record with status 201. The organisation is taken from your
        authenticated API key, never the request body. The `api_key`,
        `vertex_credentials`, and `aws_credentials` fields are write-only:
        stored encrypted and never echoed back.
      operationId: createClientModel
      requestBody:
        required: true
        description: >-
          The client model to create, including its write-only provider
          credentials.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientModelCreateFields'
            examples:
              OpenAI-compatible:
                summary: OpenAI-compatible Chat Completions endpoint (url + api_key)
                value:
                  service_type: llm
                  provider: openai-compat
                  url: https://api.openai.com/v1
                  api_key: sk-proj-example
                  model_name: gpt-4o-mini
                  model_id: gpt-4o-mini
              OpenAI Responses:
                summary: >-
                  OpenAI /v1/responses endpoint (same config shape as
                  openai-compat)
                value:
                  service_type: llm
                  provider: openai-responses
                  url: https://api.openai.com/v1
                  api_key: sk-proj-example
                  model_name: gpt-4o
              Azure OpenAI:
                summary: Azure OpenAI (adds azure_deployment and api_version)
                value:
                  service_type: llm
                  provider: azure
                  url: https://my-resource.openai.azure.com
                  api_key: azure-openai-key-example
                  azure_deployment: gpt-4o-mini-deployment
                  api_version: '2024-06-01'
                  model_name: gpt-4o-mini
              Google Vertex AI:
                summary: Google Vertex AI (service-account key, no url or api_key)
                value:
                  service_type: llm
                  provider: vertex
                  model_name: gemini-1.5-pro
                  vertex_credentials:
                    type: service_account
                    project_id: my-project
                    private_key: REDACTED
                    client_email: vertex-sa@my-project.iam.gserviceaccount.com
                  vertex_location: us-central1
                  vertex_project: my-project
              AWS speech (BYOK):
                summary: Speech BYOK with AWS SigV4 credentials (stt row)
                value:
                  service_type: stt
                  model_name: aws-transcribe
                  aws_credentials:
                    access_key_id: AKIAEXAMPLE
                    secret_access_key: REDACTED
                    region: us-east-1
      responses:
        '201':
          description: The created client model.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientModelOut'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '409':
          $ref: '#/components/responses/ConflictError'
        '422':
          $ref: '#/components/responses/ValidationError'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    ClientModelCreateFields:
      properties:
        service_type:
          type: string
          enum:
            - llm
            - stt
            - tts
          description: >-
            The kind of model: `llm` for text generation, `stt` for
            speech-to-text, or `tts` for text-to-speech.
          title: Service Type
          default: llm
        url:
          anyOf:
            - type: string
              maxLength: 2000
              minLength: 1
            - type: 'null'
          title: Url
        api_key:
          anyOf:
            - type: string
              minLength: 1
            - type: 'null'
          description: >-
            The upstream provider API key. Write-only: stored encrypted and
            never returned. Required for openai-compat, openai-responses, and
            azure; rejected for vertex.
          title: Api Key
          writeOnly: true
        model_name:
          type: string
          maxLength: 255
          minLength: 1
          description: >-
            Your alias for the model. Sent upstream as-is unless `model_id` is
            set.
          title: Model Name
        model_id:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          description: >-
            The upstream provider-facing model id when it differs from
            `model_name`. Empty or null sends `model_name` as-is.
          title: Model Id
        provider:
          anyOf:
            - type: string
              enum:
                - openai-compat
                - openai-responses
                - azure
                - vertex
            - type: 'null'
          description: >-
            The bring-your-own model provider. `openai-compat` targets an
            OpenAI-compatible Chat Completions endpoint; `openai-responses`
            targets the OpenAI /v1/responses endpoint with the same config as
            `openai-compat`; `azure` is Azure OpenAI; `vertex` is Google Vertex
            AI.
          title: Provider
        model_lab:
          anyOf:
            - type: string
              maxLength: 100
            - type: 'null'
          title: Model Lab
        azure_deployment:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          description: Azure OpenAI deployment name. Azure only.
          title: Azure Deployment
        api_version:
          anyOf:
            - type: string
              maxLength: 100
            - type: 'null'
          description: Azure OpenAI API version. Azure only.
          title: Api Version
        auth_header:
          anyOf:
            - type: string
              maxLength: 64
            - type: 'null'
          description: >-
            openai-compat and openai-responses only: a custom credential header
            name that replaces the default Authorization Bearer scheme. Rejected
            for azure and vertex.
          title: Auth Header
        vertex_credentials:
          anyOf:
            - type: object
              additionalProperties: true
            - type: 'null'
          description: >-
            Vertex only: the GCP service-account key JSON. Write-only; stored
            encrypted and never returned (responses expose
            `has_vertex_credentials`).
          title: Vertex Credentials
          writeOnly: true
        vertex_location:
          anyOf:
            - type: string
              maxLength: 100
            - type: 'null'
          title: Vertex Location
        vertex_project:
          anyOf:
            - type: string
              maxLength: 100
            - type: 'null'
          title: Vertex Project
        aws_credentials:
          anyOf:
            - type: object
              additionalProperties: true
            - type: 'null'
          description: >-
            Speech BYOK only: AWS SigV4 credentials (access_key_id,
            secret_access_key, region). Write-only; stored encrypted and never
            returned (responses expose `has_aws_credentials`).
          title: Aws Credentials
          writeOnly: true
        api_key_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: >-
            Speech BYOK only: the API key id this credential is scoped to. Null
            means the organisation default. Rejected on llm rows. Non-secret.
          title: Api Key Id
        languages:
          items:
            type: string
          type: array
          title: Languages
        regions:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Regions
        enabled:
          type: boolean
          title: Enabled
          default: true
        kwargs:
          anyOf:
            - type: object
              additionalProperties: true
            - type: 'null'
          title: Kwargs
        fallbacks:
          anyOf:
            - items:
                $ref: '#/components/schemas/LlmRouterConfigEntry'
              type: array
              maxItems: 2
            - type: 'null'
          title: Fallbacks
      type: object
      required:
        - model_name
      title: ClientModelCreateFields
      example:
        service_type: llm
        provider: openai-compat
        url: https://api.openai.com/v1
        api_key: sk-proj-example
        model_name: gpt-4o-mini
      description: >-
        The writable fields of a client model (a bring-your-own model provider
        credential). The organisation is taken from the authenticated request.
        The `api_key`, `vertex_credentials`, and `aws_credentials` fields are
        write-only and are never returned.
    ClientModelOut:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        org_id:
          type: string
          format: uuid
          title: Org Id
        api_key_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: >-
            Speech BYOK only: the API key id this credential is scoped to, or
            null for the organisation default. Non-secret.
          title: Api Key Id
        service_type:
          type: string
          enum:
            - llm
            - stt
            - tts
          description: 'The kind of model: `llm`, `stt`, or `tts`.'
          title: Service Type
        provider:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The configured provider. May be a legacy free-form label on records
            created before the current provider set.
          title: Provider
        model_lab:
          anyOf:
            - type: string
            - type: 'null'
          title: Model Lab
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
        has_api_key:
          type: boolean
          description: >-
            Whether an upstream API key is stored. The key value is write-only
            and never returned.
          title: Has Api Key
        auth_header:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The custom credential header name, or null for the default
            Authorization Bearer scheme. The credential value itself is never
            returned.
          title: Auth Header
        model_name:
          type: string
          description: The configured alias for the model.
          title: Model Name
        model_id:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The upstream provider-facing model id, or null when `model_name` is
            sent as-is.
          title: Model Id
        fallbacks:
          anyOf:
            - items:
                $ref: '#/components/schemas/LlmRouterConfigEntry'
              type: array
            - type: 'null'
          title: Fallbacks
        azure_deployment:
          anyOf:
            - type: string
            - type: 'null'
          description: The configured Azure OpenAI deployment name (Azure only).
          title: Azure Deployment
        api_version:
          anyOf:
            - type: string
            - type: 'null'
          description: The configured Azure OpenAI API version (Azure only).
          title: Api Version
        has_vertex_credentials:
          type: boolean
          description: >-
            Whether Vertex service-account credentials are stored. The value is
            write-only and never returned.
          title: Has Vertex Credentials
        has_aws_credentials:
          type: boolean
          description: >-
            Whether AWS SigV4 credentials are stored. The value is write-only
            and never returned.
          title: Has Aws Credentials
        vertex_location:
          anyOf:
            - type: string
            - type: 'null'
          title: Vertex Location
        vertex_project:
          anyOf:
            - type: string
            - type: 'null'
          title: Vertex Project
        languages:
          items:
            type: string
          type: array
          title: Languages
        regions:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Regions
        enabled:
          type: boolean
          title: Enabled
        kwargs:
          anyOf:
            - type: object
              additionalProperties: true
            - type: 'null'
          title: Kwargs
        created_at:
          type: string
          format: date-time
          title: Created At
        updated_at:
          type: string
          format: date-time
          title: Updated At
      type: object
      required:
        - id
        - org_id
        - service_type
        - provider
        - model_lab
        - url
        - has_api_key
        - auth_header
        - model_name
        - model_id
        - azure_deployment
        - api_version
        - has_vertex_credentials
        - has_aws_credentials
        - vertex_location
        - vertex_project
        - languages
        - regions
        - enabled
        - kwargs
        - created_at
        - updated_at
      title: ClientModelOut
      description: >-
        A client model as returned by the API. Credential values are never
        included; `has_api_key`, `has_vertex_credentials`, and
        `has_aws_credentials` report whether each secret is stored, and
        `fallbacks` lists the configured fallback cascade.
      example:
        id: 6a3f5b2c-1d4e-4f8a-9b0c-2e3d4f5a6b7c
        org_id: 1b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e
        api_key_id: null
        service_type: llm
        provider: openai-compat
        model_lab: null
        url: https://api.openai.com/v1
        has_api_key: true
        auth_header: null
        model_name: gpt-4o-mini
        model_id: null
        fallbacks: []
        azure_deployment: null
        api_version: null
        has_vertex_credentials: false
        has_aws_credentials: false
        vertex_location: null
        vertex_project: null
        languages: []
        regions: null
        enabled: true
        kwargs: null
        created_at: '2026-01-15T09:30:00Z'
        updated_at: '2026-01-15T09:30:00Z'
    LlmRouterConfigEntry:
      properties:
        client_model_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: >-
            Bring-your-own model reference: the id of one of your client models.
            Mutually exclusive with `catalog_model_code` (set at most one).
          title: Client Model Id
        catalog_model_code:
          anyOf:
            - type: string
              maxLength: 255
              minLength: 1
            - type: 'null'
          description: >-
            SLNG-managed model reference: a catalog model code. Mutually
            exclusive with `client_model_id`.
          title: Catalog Model Code
      type: object
      title: LlmRouterConfigEntry
      description: >-
        One slot in a config's ordered fallback cascade (``entries``).


        Exactly one of ``client_model_id`` (BYOK) or ``catalog_model_code``

        (Slng-managed) — the same XOR as the row-level model reference. Org

        ownership / catalog entitlement are checked in the service layer (needs
        the

        DB session); position in the list is the tier the sync derives
        (1-based).
      example:
        client_model_id: 6a3f5b2c-1d4e-4f8a-9b0c-2e3d4f5a6b7c
        catalog_model_code: null
    ApiErrorResponse:
      type: object
      description: Standard error envelope returned for failed requests.
      required:
        - detail
        - error
      properties:
        detail:
          type: string
          description: Short human-readable summary of the error.
        error:
          $ref: '#/components/schemas/ApiErrorDetail'
      example:
        detail: A shared secret or variable named 'STRIPE_KEY' already exists
        error:
          code: RESOURCE_CONFLICT
          message: A shared secret or variable named 'STRIPE_KEY' already exists
          request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
    ApiErrorDetail:
      type: object
      description: Structured error detail carried inside an error response.
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Stable machine-readable error code.
          example: RESOURCE_CONFLICT
        message:
          type: string
          description: Human-readable explanation of the error.
          example: A shared secret or variable named STRIPE_KEY already exists
        request_id:
          type:
            - string
            - 'null'
          description: Identifier for this request, useful when contacting support.
          example: req_01H8XY7Z9QEXAMPLE
        retryable:
          type: boolean
          description: Whether retrying the same request may succeed.
          example: false
        fields:
          type: array
          description: >-
            Per-field validation problems, when the error relates to specific
            request fields.
          items:
            type: object
            additionalProperties: true
          example: []
      example:
        code: PUBLIC_SHARED_RESOURCES_DISABLED
        message: Public shared resources are disabled for this organisation
        request_id: req_01H8XY7Z9QEXAMPLE
        retryable: false
  responses:
    UnauthorizedError:
      description: The API key is missing or invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            detail: Invalid API key
            error:
              code: AUTH_REQUIRED
              message: Invalid API key
              request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
              retryable: false
    ForbiddenError:
      description: >-
        The caller lacks permission, or the public shared-resource API is
        disabled for the organisation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          examples:
            permission_denied:
              summary: Owner or admin access required
              value:
                detail: Organisation owner or admin access required
                error:
                  code: PERMISSION_DENIED
                  message: Organisation owner or admin access required
                  request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
                  retryable: false
            api_disabled:
              summary: Public shared-resource API disabled for the organisation
              value:
                detail: >-
                  Public shared-resource API access is disabled for this
                  organisation
                error:
                  code: PUBLIC_SHARED_RESOURCES_DISABLED
                  message: >-
                    Public shared-resource API access is disabled for this
                    organisation
                  request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
                  retryable: false
    ConflictError:
      description: The request conflicts with the current state of the resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            detail: The request conflicts with the current state of the resource.
            error:
              code: RESOURCE_CONFLICT
              message: The request conflicts with the current state of the resource.
              request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
    ValidationError:
      description: Request validation failed. See error.fields for the offending fields.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            detail: >-
              Request validation failed. Fix the highlighted fields and try
              again.
            error:
              code: VALIDATION_FAILED
              message: >-
                Request validation failed. Fix the highlighted fields and try
                again.
              request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
              retryable: false
              fields:
                - path: name
                  message: >-
                    Name must be SCREAMING_SNAKE_CASE: start with a letter, then
                    letters, digits, or underscores (e.g. STRIPE_API_KEY)
    RateLimitError:
      description: >-
        The organisation exceeded its request rate limit. Retry after the window
        resets.
      headers:
        Retry-After:
          schema:
            type: integer
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            detail: Rate limit exceeded. Maximum 60 requests per 60 seconds.
            error:
              code: INTERNAL_ERROR
              message: Rate limit exceeded. Maximum 60 requests per 60 seconds.
              request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
              retryable: false
    InternalServerError:
      description: The request failed unexpectedly. Secret values are never exposed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            detail: An unexpected error occurred.
            error:
              code: INTERNAL_ERROR
              message: An unexpected error occurred.
              request_id: 018f9b2c-7e4a-7c3d-9a1b-2c3d4e5f6a7b
              retryable: false
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: SLNG API key
      description: Your SLNG consumer API key.

````