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

# Inspect a model



## OpenAPI

````yaml api-reference/openapi.json GET /v1/tools/inspect
openapi: 3.1.0
info:
  title: Spiral API
  version: '1'
  description: >-
    1. Retry automatically only on network errors and timeouts (same
    `Idempotency-Key`) and on the codes below. `retryable` and `x-should-retry`
    on the answer always win over this table (for example `RATE_LIMITED` is not
    retryable once the `day` policy is exhausted). Every other code needs a
    change before the request is sent again.


    | Code | HTTP | Retry | Wait |

    |---|---|---|---|

    | INSUFFICIENT_BALANCE | 402 | only when the problem says `retryable: true`,
    with the same `Idempotency-Key` | `Retry-After` (30 s by default) |

    | IDEMPOTENCY_IN_PROGRESS | 409 | yes, with the same `Idempotency-Key` |
    `Retry-After` (1 s by default) |

    | RATE_LIMITED | 429 | yes | `Retry-After` |

    | CONCURRENCY_LIMITED | 429 | yes | `Retry-After` (2 s by default) |

    | QUEUE_FULL | 429 | yes | `Retry-After` (2 s by default) |

    | INTERNAL_ERROR | 500 | yes, with the same `Idempotency-Key` | backoff
    (rule 2) |

    | BILLING_UNAVAILABLE | 503 | yes, with the same `Idempotency-Key` |
    `Retry-After` (5 s by default) |

    | SCHEMA_UNAVAILABLE | 503 | yes | `Retry-After` (10 s by default) |

    | PROVIDER_PAUSED | 503 | yes | `Retry-After` (60 s by default) |

    | MODEL_PAUSED | 503 | yes | `Retry-After` (60 s by default) |

    | SERVICE_UNAVAILABLE | 503 | yes, with the same `Idempotency-Key` |
    `Retry-After` (5 s by default) |


    2. Backoff: capped exponential with full jitter, `sleep = random(0, min(30
    s, 1 s × 2^attempt))`, at most 4 retries and about 2 minutes in total for a
    create.

    3. Retry-After is a floor: wait at least that long (add 0–20 % jitter).
    Magica never sends more than 60 s.

    4. Keys: send a UUIDv4 `Idempotency-Key` on every `POST /v1/runs` and store
    it with your task before sending. Reuse it for every retry of the same
    intent, including after a restart; a replay returns the original run with
    `Idempotent-Replayed: true`, never a second run or charge. Use a new key
    only to start a new run deliberately. A key is remembered for 3 days, then
    may start a new run.

    5. Unknown outcome of a create (timeout, connection reset): retry with the
    same key. Never switch to a new key until the first request is known not to
    have created a run.

    6. Failed runs: start at most one new run (new key), and only when
    `error.retryable` is true. `PROVIDER_OUTCOME_UNKNOWN` is not retryable:
    check your own results first, because the provider may have done the work.

    7. Polling: prefer webhooks. Otherwise use `GET
    /v1/runs/{id}?wait_seconds=30`, or poll by `Retry-After` on 202 and running
    responses; without it start at 1 s (search and scrape), 2 s (images), 5 s
    (video and audio), back off × 1.5 up to 30 s, and stop at a final status.
    Polling has its own rate-limit policy (`poll`), so it never consumes create
    quota.

    8. Webhooks: verify the signature over the raw body with your org's signing
    secret (any Standard Webhooks library; during a secret rotation the header
    carries two signatures and either verifies); answer 2xx fast and do the work
    afterwards (a delivery that takes over 10 s is re-sent); ignore event types
    you do not handle (types are added over time); dedupe on `webhook-id` for at
    least 7 days (every re-send carries the same one); on `truncated: true` read
    the run with `GET /v1/runs/{id}` (the body left out `output` to stay under
    receiver limits); ignore a delivery whose run `sequence` is lower than one
    already applied; download outputs within 24 hours. A webhook is sent right
    after the run is charged, so it usually carries the final charge (`sequence`
    4); when the provider's bill comes later it carries `cost.state: held`
    (`sequence` 3) and the final charge is on `GET /v1/runs/{id}` (`sequence`
    4). No separate billing event is sent.

    9. Runs cannot be canceled after submission. Poll the run or wait for its
    configured terminal webhook.
servers:
  - url: https://api.spiral.ai
security: []
paths:
  /v1/tools/inspect:
    get:
      tags:
        - Discovery
      summary: >-
        Everything needed to call one model: its input schema, pricing,
        capabilities, limits and lifecycle.
      operationId: inspect
      parameters:
        - name: provider
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            description: Provider id.
          description: Provider id.
        - name: model
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            description: Catalog id (model or tool operation).
          description: Catalog id (model or tool operation).
        - name: If-None-Match
          in: header
          required: false
          description: 'The ETag of an earlier answer: 304 while nothing changed.'
          schema:
            type: string
      responses:
        '200':
          description: The model, with its ETag.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            ETag:
              $ref: '#/components/headers/ETag'
            Deprecation:
              $ref: '#/components/headers/Deprecation'
            Sunset:
              $ref: '#/components/headers/Sunset'
          content:
            application/json:
              schema:
                type: object
                properties:
                  provider:
                    type: string
                  model:
                    type: string
                  title:
                    type: string
                  category:
                    type: string
                  execution:
                    type: string
                    enum:
                      - async
                      - sync
                  status:
                    type: string
                    enum:
                      - active
                      - deprecated
                  availability:
                    type: string
                    enum:
                      - live
                      - preview
                  allowed:
                    type: boolean
                  input_schema:
                    type: object
                    propertyNames:
                      type: string
                    additionalProperties: {}
                  output_types:
                    type: array
                    items:
                      type: string
                  priceable:
                    type: boolean
                  pricing:
                    anyOf:
                      - type: object
                        properties:
                          currency:
                            type: string
                            const: USD
                          unit:
                            type: string
                          from:
                            type: string
                          notes:
                            type: string
                        required:
                          - currency
                          - unit
                          - from
                          - notes
                      - type: 'null'
                  pricing_sentence:
                    type:
                      - string
                      - 'null'
                  capabilities:
                    type: object
                    properties:
                      cancel:
                        type: boolean
                      webhook:
                        type: boolean
                      sync:
                        type: boolean
                    required:
                      - cancel
                      - webhook
                      - sync
                  limits:
                    type: object
                    properties:
                      run_deadline_s:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      max_queue_wait_s:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      expected_duration_s:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      poll_hint_s:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      max_input_bytes:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      max_file_bytes:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      max_output_bytes:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      max_outputs:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                    required:
                      - run_deadline_s
                      - max_queue_wait_s
                      - expected_duration_s
                      - poll_hint_s
                      - max_input_bytes
                      - max_file_bytes
                      - max_output_bytes
                      - max_outputs
                  deprecated_at:
                    anyOf:
                      - type: string
                        description: RFC 3339 timestamp
                      - type: 'null'
                  retires_at:
                    anyOf:
                      - type: string
                        description: RFC 3339 timestamp
                      - type: 'null'
                required:
                  - provider
                  - model
                  - title
                  - category
                  - execution
                  - status
                  - availability
                  - allowed
                  - input_schema
                  - output_types
                  - priceable
                  - pricing
                  - capabilities
                  - limits
                  - deprecated_at
                  - retires_at
        '304':
          description: 'Not modified: If-None-Match equals the current ETag.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            ETag:
              $ref: '#/components/headers/ETag'
        '400':
          description: 'Problem: INVALID_REQUEST.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: 'Problem: UNAUTHENTICATED, API_KEY_REVOKED, API_KEY_EXPIRED.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: 'Problem: ORG_SUSPENDED, PERMISSION_DENIED.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: 'Problem: PROVIDER_NOT_FOUND, MODEL_NOT_FOUND.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '405':
          description: 'Problem: METHOD_NOT_ALLOWED.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
            Allow:
              $ref: '#/components/headers/Allow'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '410':
          description: 'Problem: MODEL_RETIRED.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '429':
          description: 'Problem: RATE_LIMITED.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: 'Problem: INTERNAL_ERROR.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '503':
          description: >-
            Problem: PROVIDER_PAUSED, MODEL_PAUSED, SCHEMA_UNAVAILABLE,
            SERVICE_UNAVAILABLE.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
            RateLimit:
              $ref: '#/components/headers/RateLimit'
            x-should-retry:
              $ref: '#/components/headers/x-should-retry'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
      security:
        - bearer: []
components:
  headers:
    X-Request-Id:
      description: >-
        `req_<ULID>`; equals `request_id` in problems and the log context. Every
        response.
      schema:
        type: string
    RateLimit-Policy:
      description: >-
        IETF draft-11, e.g. `"minute";q=600;w=60, "day";q=200000;w=86400`.
        Authenticated responses.
      schema:
        type: string
    RateLimit:
      description: >-
        IETF draft-11, e.g. `"minute";r=12;t=41`. Authenticated responses;
        `Retry-After` wins.
      schema:
        type: string
    ETag:
      description: >-
        Hash of the model's version and the price this caller sees, so it
        changes with the caller's fee (inspect).
      schema:
        type: string
    Deprecation:
      description: '`@<unix seconds of deprecated_at>` for a `deprecated` model.'
      schema:
        type: string
    Sunset:
      description: '`<HTTP-date of retires_at>` for a `deprecated` model.'
      schema:
        type: string
    x-should-retry:
      description: '`true` or `false`, mirrors `retryable`. Every error response.'
      schema:
        type: string
    Allow:
      description: The allowed methods. Every 405.
      schema:
        type: string
    Retry-After:
      description: >-
        Delay-seconds, never more than 60: every 429 and 503, 409
        `IDEMPOTENCY_IN_PROGRESS`, 402 `INSUFFICIENT_BALANCE` while an auto
        top-up is expected, and the poll hint on a 202 or a running run.
      schema:
        type: string
  schemas:
    Problem:
      type: object
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
        detail:
          type: string
        code:
          type: string
        retryable:
          type: boolean
        request_id:
          type: string
        errors:
          type: array
          items:
            type: object
            properties:
              pointer:
                type: string
              message:
                type: string
              reason:
                type: string
                enum:
                  - unknown_field
                  - missing_required
                  - wrong_type
                  - not_in_enum
                  - below_minimum
                  - above_maximum
                  - not_multiple_of
                  - too_short
                  - too_long
                  - too_few_items
                  - too_many_items
                  - pattern_mismatch
                  - invalid_format
                  - no_matching_variant
                  - invalid_combination
                  - control_field
                  - invalid_value
                  - file_too_large
                  - unsupported_media_type
                  - duration_too_long
                  - duration_too_short
                  - resolution_too_low
                  - resolution_too_high
                  - unreachable
                  - file_not_found
                  - content_policy
                  - provider_refused
              expected:
                anyOf:
                  - type: string
                  - type: number
                  - type: boolean
                  - type: 'null'
                  - type: object
                    propertyNames:
                      type: string
                    additionalProperties:
                      type:
                        - string
                        - number
                        - boolean
                        - 'null'
              received:
                anyOf:
                  - type: string
                  - type: number
                  - type: boolean
                  - type: 'null'
                  - type: object
                    propertyNames:
                      type: string
                    additionalProperties:
                      type:
                        - string
                        - number
                        - boolean
                        - 'null'
              allowed:
                type: array
                items:
                  type:
                    - string
                    - number
                    - boolean
                    - 'null'
            required:
              - pointer
              - message
            additionalProperties: false
        retry_after_seconds:
          type: integer
          minimum: -9007199254740991
          maximum: 9007199254740991
      required:
        - type
        - title
        - status
        - detail
        - code
        - retryable
        - request_id
      additionalProperties: {}
  securitySchemes:
    bearer:
      type: http
      scheme: bearer

````

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