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

# Fetch



## OpenAPI

````yaml api-reference/openapi.json POST /v1/fetch
openapi: 3.1.0
info:
  title: Seltz API
  description: >-
    REST API for the Seltz platform: context retrieval (`/v1/search`), RAG
    answers (`/v1/answer`), monitors (`/v1/monitors`), and page fetching
    (`/v1/fetch`).
  contact:
    name: Seltz API Support
    url: https://seltz.ai/contact
  license:
    name: Seltz Terms of Use
    url: https://seltz.ai/terms
  version: 1.8.0
servers:
  - url: https://api.seltz.ai
    description: Seltz API
security: []
tags:
  - name: search
    description: Search operations
  - name: answer
    description: Answer operations
  - name: monitors
    description: Monitor configuration
  - name: records
    description: The delivered records
  - name: runs
    description: Run history and per-request outcomes
  - name: agent
    description: 'Agent runs: create, poll, list, cancel'
  - name: fetch
    description: Fetch operations
paths:
  /v1/fetch:
    post:
      tags:
        - fetch
      summary: Fetch URLs as LLM-ready content
      operationId: fetch
      parameters:
        - name: x-api-key
          in: header
          description: 'Seltz API key: https://console.seltz.ai/api-keys'
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FetchRequest'
            example:
              urls:
                - https://example.com/
        required: true
      responses:
        '200':
          description: >-
            One result per requested URL. A failure to fetch a page is still a
            200, with that result's `status = "error"`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FetchResponse'
        '400':
          description: >-
            Malformed body, an out-of-bounds or duplicated `urls` entry, or an
            unavailable `formats` or `tier` value. Unrecognized fields are
            ignored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: Insufficient credits.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    FetchRequest:
      type: object
      description: Fetch request.
      properties:
        api_key:
          type:
            - string
            - 'null'
          description: >-
            API key to access the service. Either this or the `x-api-key` header
            must

            be supplied on the HTTP surface; the header takes precedence and is
            the

            documented path. On gRPC this field is the only carrier.
          default: null
        formats:
          type: array
          items:
            type: string
          description: >-
            Representations to return, as documented format names.


            Omitted, or sent empty, means `\["markdown"\]` -- a repeated field
            carries

            no presence, so the two are the same request and neither means "no

            formats".


            Documented names:


            "markdown" -- the main content as Markdown, boilerplate removed.


            An unrecognized name is rejected. Silently dropping it would return
            a body

            missing the representation the caller asked for, with nothing to
            signal

            why.
          default: []
        tier:
          type:
            - string
            - 'null'
          description: >-
            The service tier, which selects the price. Send `"pro"`. Unset
            resolves to

            `"pro"`.


            An unrecognized value is rejected rather than defaulted: the value
            selects

            a price, and quietly billing a tier the caller did not name is worse
            than

            refusing.
          default: null
        timeout_ms:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            Wall-clock budget for one URL, in milliseconds.


            Applies per URL, not to the batch: URLs are fetched concurrently, so
            a

            batch takes roughly as long as its slowest entry rather than the
            sum. A

            URL that exceeds the budget gets `error.code = "timeout"`; the
            others in

            the same request are unaffected.


            Unset means the service default. Values are clamped to the service

            maximum.
          default: null
          minimum: 0
        urls:
          type: array
          items:
            type: string
          description: >-
            The URLs to fetch. At least one, at most 20.


            Each must be an absolute `http` or `https` URL of at most 2048
            bytes. An

            empty list, more than 20 entries, a duplicate entry, or an over-long
            entry

            is rejected before any billing: duplicates because

            `FetchResult.requested_url` is the correlation key and a repeated
            key is

            ambiguous. A URL that parses but cannot be fetched -- a host that
            does not

            resolve, an origin that refuses, a document that is not an HTML page
            -- is

            reported inside a `200` as that URL's error result, not as a
            rejection.
          default: []
    FetchResponse:
      type: object
      description: Fetch response -- one result per requested URL.
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/FetchResult'
          description: >-
            One entry per entry in `FetchRequest.urls`, successful or not, in
            the order

            the URLs were requested.


            Correlate on `FetchResult.requested_url` rather than on position.
            That is

            the key a duplicate URL would make ambiguous, which is why the
            request

            rejects one.
          default: []
    ErrorEnvelope:
      type: object
      description: 'The `{"error": {...}}` envelope a non-200 carries.'
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/EnvelopeError'
          description: The rejection.
    FetchResult:
      type: object
      description: The outcome for one URL.
      required:
        - status
      properties:
        content_type:
          type:
            - string
            - 'null'
          description: |-
            The origin's declared media type for the main document, without
            parameters. Unset when the origin declared none.
          default: null
        error:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/FetchError'
              description: >-
                Why the fetch failed. Set when `status` is the error status,
                unset

                otherwise.
          default: null
        fetched_at:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/google.protobuf.Timestamp'
              description: When the content was retrieved from the origin.
          default: null
        final_url:
          type:
            - string
            - 'null'
          description: >-
            The URL the content actually came from, after HTTP redirects and any

            client-side navigation. Equal to `requested_url` when nothing
            redirected.
          default: null
        http_status_code:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            The origin's HTTP status code for the main document. Unset when no
            network

            response was observed for the navigation.
          default: null
          minimum: 0
        markdown:
          type:
            - string
            - 'null'
          description: >-
            The page's main content as Markdown, with navigation, footers, and
            ads

            removed.
          default: null
        requested_url:
          type: string
          description: >-
            The URL this answers, echoed verbatim from the request -- byte for
            byte,

            never normalized, and never the post-redirect URL. This is the
            correlation

            key. Where redirects landed is `final_url`.
          default: ''
        status:
          oneOf:
            - $ref: '#/components/schemas/FetchStatus'
              description: >-
                Whether this result carries content.


                Branch on this field, never on whether a given content field is
                present: a

                format the page could not produce is unset on an otherwise
                successful

                result, so "markdown is absent" does not mean "the fetch
                failed".


                A failed fetch is still HTTP 200, with the error status on the
                result.
          default: ok
    EnvelopeError:
      type: object
      description: |-
        The failure inside a non-200 envelope. Its `code` is `SCREAMING` and the
        set is closed, because it is a pure function of the gRPC code.
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: A stable name for the rejection.
        message:
          type: string
          description: What went wrong, in prose. Never an internal service name.
    FetchError:
      type: object
      description: Why one URL failed.
      properties:
        code:
          type: string
          description: >-
            A stable, machine-readable reason. A client must treat an
            unrecognized

            code as a generic failure rather than rejecting the result.


            Documented codes:


            "invalid_url"              -- not a parseable absolute URL.

            "unsupported_scheme"       -- parseable, but not `http` or `https`.

            "url_not_accessible"       -- DNS, connection, TLS, or navigation

            failure reaching the origin.

            "timeout"                  -- the fetch did not finish within

            `timeout_ms`.

            "unsupported_content_type" -- the document is not an HTML page.
            PDFs,

            images, archives, and other binaries are

            out of scope. Refused either before the

            fetch, from the URL, or after it, from the

            media type the origin declared; the caller

            sees one code either way, because from

            their side it is one fact.

            "extraction_failed"        -- the page was fetched, but no requested

            format could be produced from it.

            "upstream_error"           -- the fetch path itself failed. Ours,
            not

            the URL's.
          default: ''
        message:
          type: string
          description: >-
            A human-readable explanation. Always set when this message is
            present:

            `FetchError` itself is optional on the result, so an absent error is

            absent whole, and there is no state where a failure arrives without
            a

            reason. For operators and logs. Never parse it -- branch on `code`.
            The

            wording of any given message may change at any time.
          default: ''
    google.protobuf.Timestamp:
      type: string
      description: A timestamp in RFC 3339 format
      examples:
        - '2025-04-11T12:00:00Z'
        - '2025-04-11T12:00:00.123456789Z'
    FetchStatus:
      type: string
      description: Whether a `FetchResult` carries content.
      enum:
        - ok
        - error

````