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

# List the organization's providers



## OpenAPI

````yaml /api-reference/openapi.yaml get /api/llm-gateway/admin/providers
openapi: 3.1.0
info:
  title: Barndoor.ai Public API
  description: Unified public API specification for Barndoor.ai platform
  version: 2.18.0
servers:
  - url: https://{host}
    description: Barndoor public API
    variables:
      host:
        default: platform.barndoor.ai
        description: >-
          The host serving your Barndoor deployment. Defaults to production;
          override it for another environment or a dedicated deployment.
security:
  - ApiKey: []
  - OAuth2:
      - openid
      - profile
      - email
tags:
  - name: dlp
    x-group: Data Control Center
  - name: identity
    x-group: Identity
  - name: llm-gateway
    x-group: LLM Gateway
  - name: notification
    x-group: Notifications
  - name: policy
    x-group: Policies
  - name: registry
    x-group: MCP Gateway
  - name: system-management
    x-group: Log Exports
paths:
  /api/llm-gateway/admin/providers:
    get:
      tags:
        - llm-gateway
      summary: List the organization's providers
      operationId: list_providers
      responses:
        '200':
          description: The requested record
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Provider'
        '401':
          description: Missing or invalid credentials
        '403':
          description: Caller is not permitted to act on this resource in this organization
components:
  schemas:
    Provider:
      allOf:
        - $ref: '#/components/schemas/ChangeAttribution'
          description: >-
            Who created and last changed this provider, and why (BCP-3998).


            Absent in the resolve/route queries -- the request path never reads
            it

            -- and read with `try_get`, so those rows come back unattributed
            rather

            than failing. That is indistinguishable from a row nobody has
            touched

            since V75, which is the correct thing for a value the request path
            was

            never given.
        - type: object
          required:
            - id
            - org_id
            - name
            - model_provider
            - auth_type
            - base_url
            - secret_path
            - enabled
            - settings
            - created_at
            - updated_at
            - health_status
            - enforce_health_check
            - model_sync_mode
            - billing_mode
          properties:
            auth_type:
              type: string
            base_url:
              type: string
            billing_mode:
              $ref: '#/components/schemas/BillingMode'
              description: >-
                Whether the gateway records a per-token cost for this provider's

                traffic (V69 / BCP-3876). `PerToken` for every provider that has
                not

                opted in, which is the default and the back-compat value.


                The request path does **not** read this field: billing consults

                [`ai_governance::CostCalculator`]'s own cached not-metered set,
                which

                is refreshed from the same query as pricing. This exists for the
                admin

                API surface and the audit trail.
            billing_note:
              type:
                - string
                - 'null'
              description: |-
                Optional free-text context for the arrangement (max 200 chars).
                Human-readable only — never parsed, never aggregated.
            billing_reason:
              oneOf:
                - $ref: '#/components/schemas/BillingReason'
                  description: >-
                    How the vendor bills this provider. Required when
                    `billing_mode` is

                    `NotMetered`, optional otherwise (V69 CHECK-enforced) — a
                    subscription

                    billing overages is both per-token and a subscription.
                    Purely

                    descriptive: no code branches on it, which is what lets a
                    new reason be

                    added without touching the billing path.
                - type: 'null'
            catalog_id:
              type:
                - string
                - 'null'
              format: uuid
            catalog_slug:
              type:
                - string
                - 'null'
            connection_id:
              type:
                - string
                - 'null'
              format: uuid
            created_at:
              type: string
              format: date-time
            enabled:
              type: boolean
            enforce_health_check:
              type: boolean
              description: >-
                Operator override for the health gate (V46). When `true`
                (default)

                routing requires `health_status <> 'unhealthy'`; when `false`
                the gate

                is bypassed and the provider serves regardless of probe results
                (we

                still probe and surface health). Lets an admin force traffic
                through a

                false-positive probe.
            health_checked_at:
              type:
                - string
                - 'null'
              format: date-time
              description: >-
                When the last connectivity probe ran (NULL until the first
                probe).
            health_detail:
              type:
                - string
                - 'null'
              description: >-
                Reason for the last `unhealthy` or `unverified` probe (NULL if
                healthy or never probed).
            health_status:
              type: string
              description: >-
                Observed upstream reachability, recorded separately from
                `enabled`

                (operator intent) so the system never overwrites the toggle
                (V45).

                One of `unverified` | `healthy` | `unhealthy`. `unverified` is
                the

                back-compat default and also covers provider families we don't
                probe

                (Bedrock/Vertex/Azure, claude_oauth, codex_oauth). A provider
                serves traffic only

                when `enabled` AND `health_status <> 'unhealthy'`: a failed
                probe

                auto-suspends it from routing (see `resolve_*`) without
                disabling it,

                and it resumes once a probe records it healthy again.
            id:
              type: string
              format: uuid
            model_provider:
              type: string
            model_sync_mode:
              $ref: '#/components/schemas/ModelSyncMode'
              description: >-
                Whether this provider tracks Barndoor's model catalog, and how
                far

                (V63 / BCP-3811). `Off` for every provider that has not opted
                in,

                which is the default and the back-compat value.
            name:
              type: string
            org_id:
              type: string
              format: uuid
            request_timeout_secs:
              type:
                - integer
                - 'null'
              format: int32
              description: >-
                Provider-tier total-request timeout override (non-streaming).

                Operator-only and `None` by default: the effective value is
                written

                at the route tier (`model_mappings`), so this only applies if a
                route

                row somehow leaves it unset. Range

                `TOTAL_REQUEST_TIMEOUT_MIN_SECS..=TOTAL_REQUEST_TIMEOUT_MAX_SECS`
                is

                enforced by the CHECK constraint (see `proxy::timeouts`).
            secret_path:
              type: string
            settings: {}
            stream_idle_timeout_secs:
              type:
                - integer
                - 'null'
              format: int32
              description: >-
                Provider-tier stream-idle timeout override (streaming).
                Operator-only

                and `None` by default; the effective value is written at the
                route

                tier (`model_mappings`). Range

                `STREAM_IDLE_TIMEOUT_MIN_SECS..=STREAM_IDLE_TIMEOUT_MAX_SECS` is

                enforced by the CHECK constraint (see `proxy::timeouts`).
            updated_at:
              type: string
              format: date-time
    ChangeAttribution:
      type: object
      description: >-
        The attribution carried on an admin-configurable row, as returned to the

        portal.


        Every field is `Option` and nothing is backfilled: a row that predates
        V75

        has no truthful actor to attribute it to, and inventing one would be
        worse

        than rendering a placeholder. Rows pick up attribution on their first

        write.
      properties:
        created_by_email:
          type:
            - string
            - 'null'
        created_by_name:
          type:
            - string
            - 'null'
        created_by_user_id:
          type:
            - string
            - 'null'
          format: uuid
        last_change_note:
          type:
            - string
            - 'null'
          description: >-
            Optional free text explaining *why* the last change was made

            ("Raised for the Q3 batch job", "Vendor deprecated the old
            endpoint").


            Admin-authored and rendered in the portal, so it is untrusted input:

            length-capped here, escaped on render.
        last_modified_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the change named by `last_modified_by_*` happened.


            Its own column rather than the row's `updated_at`, because
            `updated_at`

            is bumped by writes nobody is attributed for -- pairing the two
            would

            date a named admin's edit to a background job's clock. See the V75

            migration for the full reasoning.
        last_modified_by_email:
          type:
            - string
            - 'null'
        last_modified_by_name:
          type:
            - string
            - 'null'
        last_modified_by_user_id:
          type:
            - string
            - 'null'
          format: uuid
    BillingMode:
      type: string
      description: >-
        Whether the gateway computes a per-token cost for a provider. Persisted
        as

        a `VARCHAR(16)` constrained to `per_token | not_metered` (see migration

        V69, BCP-3876).


        Deliberately binary, with the *why* held separately in
        [`BillingReason`].

        The reason list is open-ended; this question is not, and never will be.

        Folding both into one enum would make every "is this zero-cost" check
        grow

        an OR-list as reasons are added, and would need a [`PricingSource`]
        variant

        per reason — an enum whose values reach ClickHouse, the reporting
        labels, a

        frontend union type and three UI modules.


        [`PricingSource`]: ai_governance::PricingSource
      enum:
        - per_token
        - not_metered
    BillingReason:
      type: string
      description: >-
        How the vendor bills a provider. Persisted as a nullable `VARCHAR(16)`,

        required when `billing_mode = 'not_metered'` and optional otherwise (V69

        CHECK-enforced).


        **Independent of [`BillingMode`], not paired with it.** A subscription
        that

        bills overages beyond the plan is genuinely per-token *and* genuinely a

        subscription; requiring the two to agree made that unrepresentable. What

        survives is the half worth keeping: a provider must not stop recording
        cost

        without saying why.


        **Label only — nothing branches on this.** That is the point of
        separating

        it from [`BillingMode`]: adding a reason touches this enum, its label
        maps

        and the CHECK constraint, and never the billing path. If a proposed

        category needs different *behaviour* (prepaid credits drawing down a

        balance, committed spend needing a floor), it is a feature, not a
        variant

        here.
      enum:
        - subscription
        - local
        - external
        - other
    ModelSyncMode:
      type: string
      description: >-
        Whether a provider tracks Barndoor's model catalog, and how far.
        Persisted

        as a `VARCHAR(16)` constrained to `off | additive | full` (see migration

        V63).


        The three-way split is the whole point: an org that wants new models

        without the gateway ever removing anything, and an org that also wants

        retired models cleaned up, are asking for different things and both are

        legitimate. Retirement stays a separate step up rather than riding along

        with additions, because it is the only one of the two that can take a
        route

        out of service.
      enum:
        - 'off'
        - additive
        - full
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: >-
        A Barndoor API key, sent as `Authorization: Bearer <key>`. Keys are
        prefixed `bdai_` and are opaque — do not attempt to decode one.
        Interchangeable with an OAuth 2.0 access token.
    OAuth2:
      type: oauth2
      x-issuer: https://auth.barndoor.ai/realms/barndoor
      description: >-
        An OAuth 2.0 access token from Barndoor's identity provider, sent as
        `Authorization: Bearer <token>`. Public clients must use PKCE.
        Interchangeable with an API key.
      flows:
        authorizationCode:
          authorizationUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/auth
          tokenUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/token
          scopes:
            openid: Issue an OIDC ID token identifying the caller.
            profile: Read the caller's basic profile claims.
            email: Read the caller's email address.
            offline_access: Issue a refresh token. Optional — no operation requires it.
        clientCredentials:
          tokenUrl: >-
            https://auth.barndoor.ai/realms/barndoor/protocol/openid-connect/token
          scopes:
            openid: Issue an OIDC ID token identifying the caller.
            profile: Read the caller's basic profile claims.
            email: Read the caller's email address.
            offline_access: Issue a refresh token. Optional — no operation requires it.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.