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

# List FAQ items

> Retrieve a paginated list of FAQ items.

**Access:** an API key with `content:faq-items:read` (or a master above it: `content:faq-items:all`, `content:all`, `admin:all`) reads the published documents; drafts (`aposMode=draft`) need `content:faq-items:write` (or a master above it). A signed-in person reads as far as their own permissions allow, and anyone else reads the published documents’ public fields.

**Rate limit:** the key’s own reads-per-minute limit, set when the key is created (default 600); over it, 429 with `Retry-After`.



## OpenAPI

````yaml /api-reference/openapi.yaml get /faq-item
openapi: 3.1.0
info:
  title: Fetchski Attract CMS API
  description: >-
    Auto-generated OpenAPI spec for this Fetchski site instance. Authenticate
    machine-to-machine requests with an API key by sending the header
    `Authorization: ApiKey <token>`. Keys are issued in the CMS (API Keys) and
    carry scopes that limit them to specific actions. Each key also has its own
    security policy, chosen when it is created: a signing mode (token only,
    signed writes, or every request signed with the key’s signing secret via
    `X-Fetchski-Timestamp` + `X-Fetchski-Signature`), an optional network
    allowlist, and reads/writes-per-minute limits (429 with `Retry-After` over
    them). Some routes require a signature from every key — see each route.
  version: 1.0.0
servers:
  - url: https://{host}/api/v1
    description: 'Your site: set `host` to its host name.'
    variables:
      host:
        default: acme.example
security: []
tags:
  - name: Authentication
    description: >-
      Sign in as a person to get a bearer token or a session cookie.
      Integrations use an API key instead: send `Authorization: ApiKey <token>`.
  - name: SDK Packages
    description: >-
      The site’s own npm registry and Composer repository for the Attract SDKs,
      so an app installs them with one of the site’s API keys. Point npm, pnpm,
      Bun or Composer at them; the SDKs never call them.
  - name: Pages
    description: 'The page tree: each page’s content, place and URL.'
  - name: Global Content
    description: Site-wide content and settings every page shares.
  - name: Redirects
    description: Old URLs and where they now send visitors.
  - name: Internationalization
    description: The site’s locales.
  - name: Languages
    description: >-
      The site’s languages: the main language’s name and every further
      language’s name, code and Public switch. A save applies at once: a new
      language gets its home page and its own addresses (/fr/…), and its pages
      are then translated with each type’s localize routes.
  - name: Page Templates
    description: >-
      The site’s whole-page starting arrangements. They are not pages of the
      site (the Pages list leaves them out for API keys): read one, then make a
      page from it with Pages → create and `_copyingId` (`copyingId` in the
      SDKs).
  - name: Blog Posts
    description: The blog’s posts, and importing them from Markdown or MDX.
  - name: Blog Categories
    description: The categories posts are filed under.
  - name: Authors
    description: The people posts are credited to.
  - name: Team Members
    description: The people the Team section shows.
  - name: Testimonials
    description: Quotes from customers.
  - name: FAQ Items
    description: Questions and their answers.
  - name: FAQ Categories
    description: The groups questions are sorted into.
  - name: Google Reviews
    description: Reviews from the business’s Google profile, synced on a schedule.
  - name: Instagram Posts
    description: Posts from the connected Instagram account, synced on a schedule.
  - name: Service Areas
    description: The places the business serves, for the service map.
  - name: Cookies
    description: The cookies the consent banner declares.
  - name: Media
    description: The Images and Files libraries, and their tags.
  - name: Videos
    description: The Videos library.
  - name: Image Folders
    description: The folders that organize the Images library.
  - name: File Folders
    description: The folders that organize the Files library.
  - name: Video Folders
    description: The folders that organize the Videos library.
  - name: Photo Albums
    description: Hand-picked, ordered sets of photos for galleries.
  - name: Photo Feeds
    description: >-
      Feeds that collect photos from a connected photo source into the Images
      library on a schedule.
  - name: Attachments
    description: Uploading files and cropping images.
  - name: Fetchski Media
    description: >-
      Read-only discovery over the Images and Videos libraries: find what to
      reference in an MDX blog import, or which file to use, with its URLs.
  - name: Forms
    description: The site’s forms and their fields.
  - name: Form Submissions
    description: >-
      What visitors sent through the site’s forms. Submissions hold personal
      details: give a key `forms:read` only where it is needed.
  - name: Conversion Events
    description: >-
      The conversion event log — one record per conversion, with its attribution
      and consent snapshot and its delivery to each ad platform. Read it
      incrementally, post facts from other systems (a reservation purchase, a
      lead outcome), and adjust them (refunds, cancellations). One event ID
      travels everywhere as the platforms’ de-duplication key.
  - name: Visitor Attribution
    description: >-
      Per-visitor attribution on this site: first touch, last ad or campaign
      touch, and the ad platforms’ browser IDs. The join other systems use to
      attach a purchase to the marketing-site journey that led to it.
  - name: Ads Metrics
    description: >-
      Aggregates for dashboards: ad-click landings and conversions, by day,
      platform, campaign and more.
  - name: Conversions
    description: >-
      Conversion definitions — the visitor actions (a lead, a call click, a
      booking, a purchase) this site reports to the ad platforms, each with a
      row per platform. Managed by administrators in the CMS.
  - name: Webhooks
    description: >-
      Push notifications of form submissions and conversion-event changes to the
      site’s Webhook Destinations — signed with each destination’s own secret,
      retried for a day, at-least-once. Set destinations up in the CMS (Webhook
      Destinations, for people granted “Manage webhook destinations”): URL,
      events, optional filters and custom headers, and the signing secret shown
      once.
  - name: Request Log
    description: >-
      The page views the site captured (Connections → Tracking → Request log),
      and the query parameters on them: campaign tags and ad click IDs.
paths:
  /faq-item:
    get:
      tags:
        - FAQ Items
      summary: List FAQ items
      description: >-
        Retrieve a paginated list of FAQ items.


        **Access:** an API key with `content:faq-items:read` (or a master above
        it: `content:faq-items:all`, `content:all`, `admin:all`) reads the
        published documents; drafts (`aposMode=draft`) need
        `content:faq-items:write` (or a master above it). A signed-in person
        reads as far as their own permissions allow, and anyone else reads the
        published documents’ public fields.


        **Rate limit:** the key’s own reads-per-minute limit, set when the key
        is created (default 600); over it, 429 with `Retry-After`.
      operationId: listFaqItems
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PerPage'
        - $ref: '#/components/parameters/Search'
        - $ref: '#/components/parameters/AposMode'
        - $ref: '#/components/parameters/AposLocale'
        - $ref: '#/components/parameters/RenderAreas'
        - $ref: '#/components/parameters/Slug'
        - $ref: '#/components/parameters/Fields'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FaqItemList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - ApiKeyAuth:
            - content:faq-items:read
        - BearerAuth: []
        - {}
      x-codeSamples:
        - lang: typescript
          label: TypeScript
          source: |-
            import { createSiteClient } from '@fetchski/attract-cms-sdk';

            const site = createSiteClient();
            const faqItemList = await site.faqItems().listFaqItems();
        - lang: php
          label: Laravel
          source: |-
            use Fetchski\AttractCmsLaravel\Facades\Attract;

            $faqItemList = Attract::faqItems()->listFaqItems();
components:
  parameters:
    Page:
      name: page
      in: query
      description: Page number for pagination (1-based)
      required: false
      schema:
        type: integer
        minimum: 1
        default: 1
      example: 2
    PerPage:
      name: perPage
      in: query
      description: >-
        Documents per page. Each content type has its own default (core’s is 50;
        a type may set another). There is no upper limit: a large value answers
        the whole list at once, which is slow on a big one.
      required: false
      schema:
        type: integer
        minimum: 1
      example: 25
    Search:
      name: search
      in: query
      description: >-
        Matches documents by their text. Ignored for the public and API keys on
        a type whose public fields leave some out (a search would match the
        hidden ones).
      required: false
      schema:
        type: string
      example: headless cms
    AposMode:
      name: aposMode
      in: query
      description: >-
        `published` (the default) or `draft`. Drafts need a credential that may
        see them: an API key with the type’s write scope
        (`content:<type>:write`), or a signed-in editor. The public and a key
        with only the read scope get 403.
      required: false
      schema:
        type: string
        enum:
          - draft
          - published
        default: published
      example: published
    AposLocale:
      name: aposLocale
      in: query
      description: >-
        The locale to read or write, e.g. `en` (default: the site’s default
        locale).
      required: false
      schema:
        type: string
        example: fr
    RenderAreas:
      name: render-areas
      in: query
      description: >-
        true: each area’s widgets come back rendered as HTML (`_rendered`),
        beside their data.
      required: false
      schema:
        type: boolean
        default: false
      example: true
    Slug:
      name: slug
      in: query
      description: >-
        Only the document with exactly this slug: a list of one, or an empty
        list when none has it. Use it to find a document by the name in its URL.
      required: false
      schema:
        type: string
      example: getting-started
    Fields:
      name: fields
      in: query
      description: >-
        Only these fields of each document, beside its `_id`:
        `fields=title&fields=slug`, or `fields=title,slug`. Use it to find a
        document’s `_id` without reading every field of every document. A page
        keeps its place in the tree (`_children`). A field the type lacks is
        refused (400) with the list of its fields; the public, and an API key
        without the type’s read scope, may name only its public fields.
      required: false
      style: form
      explode: true
      schema:
        type: array
        items:
          type: string
      example:
        - title
        - slug
  schemas:
    FaqItemList:
      type: object
      description: A page of FaqItem documents.
      required:
        - results
        - pages
        - currentPage
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/FaqItem'
          description: This page’s documents; empty past the last page.
        pages:
          type: integer
          description: Pages in the whole list (0 when it is empty).
        currentPage:
          type: integer
          description: This page, from 1.
    FaqItem:
      type: object
      properties:
        title:
          type: string
          title: Question
          description: >-
            The question exactly as a visitor would ask it — it renders as the
            accordion row and in the page’s FAQ structured data.
          default: ''
        answer:
          title: Answer
          description: >-
            Widgets, top to bottom: send `{ "items": [ … ] }`, one object per
            widget with its `type`. Writing it replaces the whole area.
          allOf:
            - $ref: '#/components/schemas/RichTextMax1Area'
        _category:
          type:
            - array
            - 'null'
          items:
            type: object
            additionalProperties: true
          title: Category
          description: >-
            Optional. FAQ sections can group questions under category
            subheadings and filter to specific categories. Manage the list under
            FAQ Categories. The related `faq-category` documents, in order
            (empty when none). To set it, send a list of `{ "_id": "…" }`, one
            per document (one at most); a document the site can’t find is left
            out.
          maxItems: 1
        featured:
          type:
            - boolean
            - 'null'
          title: Featured
          description: >-
            Hand-curation flag: FAQ sections can show only featured questions —
            e.g. a short top-questions block on the home page.
          default: false
        sortOrder:
          type:
            - integer
            - 'null'
          title: Sort order
          description: Questions are listed lowest number first — the explicit FAQ order.
          default: 0
        slug:
          type: string
          description: >-
            The URL name: lowercase words joined by hyphens (letters outside
            a–z, even emoji, are kept).
          title: Slug
          default: ''
          x-fetchski-write-optional: Left out, it’s made from the title.
        visibility:
          type:
            - string
            - 'null'
          title: Visibility
          description: Select whether this content is public or private
          default: public
          enum:
            - public
            - loginRequired
            - null
        scheduledPublish:
          type:
            - string
            - 'null'
          description: An ISO 8601 date and time, e.g. `2026-10-21T14:30:00.000Z`.
        scheduledUnpublish:
          type:
            - string
            - 'null'
          description: An ISO 8601 date and time, e.g. `2026-10-21T14:30:00.000Z`.
        faqFontOverrides:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/FaqItemFaqFontOverridesItem'
          title: Typeface for this card
          description: >-
            Optional. Set part of this question’s card in a different typeface.
            Leave empty to follow the section (and the site fonts).
          default: []
          maxItems: 4
        source:
          type:
            - string
            - 'null'
          title: Source
          description: >-
            Set automatically. Demo placeholders are removed the moment a real
            question is published.
          default: manual
          enum:
            - manual
            - demo
            - null
          readOnly: true
        sourceId:
          type:
            - string
            - 'null'
          title: Source ID
          description: Internal de-duplication key set by the demo seed.
          default: ''
          readOnly: true
        archived:
          type:
            - boolean
            - 'null'
          title: Archived
          default: false
          description: >-
            In the archive: kept, but out of every list and off the site until
            it is restored. `false` (or null) for a live document.
        _id:
          type: string
          title: Document ID
          readOnly: true
          description: >-
            The document’s id. On a type with drafts it ends in its locale and
            mode (`…:en:published`, `…:en:draft`): the part before the first
            colon is its `aposDocId`, shared by both copies. The `{_id}` the
            type’s routes take.
        type:
          type: string
          title: Document Type
          readOnly: true
          description: 'The document type’s name: always this type’s.'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
          title: Created At
          readOnly: true
          description: When it was created (ISO 8601).
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
          title: Updated At
          readOnly: true
          description: When it last changed (ISO 8601).
        aposShareKey:
          type:
            - string
            - 'null'
          description: >-
            The draft’s preview share key, while its share link is on: the link
            is the draft’s `_url` with `aposShareKey` and `aposShareId` (the
            draft’s `_id`) in its query. Absent otherwise, and on published
            documents.
          example: k3v9x2m7q1z8w4p6
          readOnly: true
      required:
        - title
        - answer
        - slug
        - _id
        - type
      description: FaqItem content type
    ApiError:
      type: object
      description: >-
        An error answer: the error’s name, a message saying what is wrong, and
        details by error.
      required:
        - name
      properties:
        name:
          type: string
          description: >-
            The error’s name: `invalid`, `required`, `unauthorized`,
            `forbidden`, `notfound`, `conflict`, `locked`, `tooManyRequests`,
            `error` (a server failure)…
        message:
          type: string
          description: What is wrong, and how to fix it.
        data:
          type: object
          additionalProperties: true
          description: >-
            Details, by error: `errors` (one entry per field problem, each with
            its `path`), `retryAfter` (seconds, on 429), `permission`…
    RichTextMax1Area:
      type: object
      description: >-
        Content made of widgets, as the site stores it: send `{ "items": [ … ]
        }`, one object per widget, top to bottom. It takes
        `@apostrophecms/rich-text` widgets; an item of any other type is
        dropped. At most 1. Writing it replaces the whole area.
      properties:
        metaType:
          type: string
          enum:
            - area
          description: Always `area`.
        _id:
          type: string
          description: 'The area’s id, set by the site: leave it out when you write one.'
        items:
          type: array
          description: >-
            The widgets, top to bottom. Each is an object with its `type` and
            that widget’s own fields; `_id` and `metaType` may be left out (the
            site sets them).
          items:
            $ref: '#/components/schemas/RichTextWidget'
          maxItems: 1
      additionalProperties: true
      example:
        items:
          - type: '@apostrophecms/rich-text'
            content: <p>Hello from the API.</p>
    FaqItemFaqFontOverridesItem:
      type: object
      properties:
        _id:
          type: string
          description: The row’s id, unique in its array.
        target:
          type:
            - string
            - 'null'
          title: Apply to
          description: >-
            Which text this typeface replaces. Rows apply in order, so a broad
            row (Everything) followed by a narrow one (Headings) gives the
            section a base face plus an exception.
          default: all
          enum:
            - all
            - heading
            - body
            - eyebrow
            - button
            - code
            - null
        source:
          type:
            - string
            - 'null'
          title: Typeface
          description: >-
            Where the typeface comes from. The first option costs nothing extra
            — those faces are already loaded. The others load an additional font
            on pages that use this section.
          default: slot
          enum:
            - slot
            - curated
            - cdn
            - upload
            - null
        slot:
          type:
            - string
            - 'null'
          title: Site typeface
          description: >-
            Set in Site design → Typography. Following the site’s own faces
            keeps a section on-brand and adds no download.
          default: display
          enum:
            - display
            - body
            - accent
            - null
        curated:
          type:
            - string
            - 'null'
          title: Curated pick
          description: >-
            Vetted families from Bunny Fonts and Fontshare, with their available
            weights already verified.
          default: archivo
          enum:
            - archivo
            - bricolage-grotesque
            - clash-display
            - courier-prime
            - dm-mono
            - dm-sans
            - fira-code
            - fraunces
            - general-sans
            - ibm-plex-mono
            - ibm-plex-sans
            - inconsolata
            - inter
            - jetbrains-mono
            - karla
            - lora
            - manrope
            - nunito-sans
            - outfit
            - playfair-display
            - public-sans
            - red-hat-mono
            - satoshi
            - sentient
            - sora
            - source-code-pro
            - source-sans-3
            - source-serif-4
            - space-grotesk
            - space-mono
            - spline-sans-mono
            - supreme
            - switzer
            - syne
            - ubuntu-mono
            - unbounded
            - victor-mono
            - work-sans
            - zodiak
            - null
        cdnProvider:
          type:
            - string
            - 'null'
          title: Provider
          description: >-
            Where to browse for the family. Pick one, then follow the link below
            to find the exact name.
          default: bunny
          enum:
            - bunny
            - fontshare
            - null
        cdnFamily:
          type: string
          title: Family name
          description: >-
            Exactly as the provider’s catalog spells it, e.g. "Space Grotesk" or
            "Clash Display". A name the provider doesn’t have loads nothing and
            this row is ignored.
          default: ''
        cdnWeights:
          type: string
          title: Weights
          description: >-
            Comma-separated weights to load, e.g. 400, 700. Empty loads 400,
            500, 700. Weights the family doesn’t ship are skipped by the CDN and
            synthesized by the browser (faux bold) — but a family that ships
            only ONE weight (Acme, for instance) loads nothing at all unless
            that weight is among these, so set it explicitly if the typeface
            doesn’t appear.
          default: ''
        uploads:
          type: array
          items:
            $ref: '#/components/schemas/FaqItemFaqFontOverridesItemUploadsItem'
          title: Font files
          description: >-
            One file per weight/style of the SAME typeface. woff2 strongly
            recommended (smallest, universally supported); woff/ttf/otf also
            accepted.
          default: []
          maxItems: 4
        fallback:
          type:
            - string
            - 'null'
          title: Fallback style
          description: >-
            Generic system font shown while this typeface loads (and if it
            fails). Curated picks set this automatically.
          default: sans
          enum:
            - sans
            - serif
            - mono
            - null
      additionalProperties: true
    RichTextWidget:
      type: object
      properties:
        type:
          type: string
          enum:
            - '@apostrophecms/rich-text'
          description: 'The widget’s type: always `@apostrophecms/rich-text`.'
        _id:
          type: string
          description: >-
            The widget’s id, unique on the page. Leave it out for a new widget
            (the site sets one); keep it to change a widget that is there.
        metaType:
          type: string
          enum:
            - widget
          description: Always `widget`.
        content:
          type: string
          format: html
          description: >-
            The text as HTML, e.g. `<h2>Our story</h2><p>It began with
            <strong>one</strong> idea.</p>`. The site keeps the tags and styles
            this area’s editor offers (paragraphs, headings, bold, italic,
            links, lists…) and removes the rest.
          example: <p>Hello from the API.</p>
        sectionCss:
          type:
            - object
            - 'null'
          description: >-
            CSS for this one section, typed into the slot of the part it styles.
            It wins over Site design → Custom CSS. Nested rules like &:hover,
            @media (width &gt;= 48rem) and [data-theme="light"] & work inside a
            slot.
          properties:
            slots:
              type: object
              additionalProperties:
                type: string
              description: The CSS typed into each part slot, by slot name.
            css:
              type: string
              description: 'The compiled CSS (read only: rebuilt from `slots`).'
            mark:
              type: string
              description: The site’s check mark for `css` (read only).
          title: Custom CSS
      required:
        - type
      description: >-
        A `@apostrophecms/rich-text` widget: its `type` and its own fields. A
        field left out takes its default.
      additionalProperties: true
    FaqItemFaqFontOverridesItemUploadsItem:
      type: object
      properties:
        _id:
          type: string
          description: The row’s id, unique in its array.
        file:
          type: object
          description: File attachment reference
          title: Font file
        weight:
          type:
            - string
            - 'null'
          title: Weight
          default: '400'
          enum:
            - '100'
            - '200'
            - '300'
            - '400'
            - '500'
            - '600'
            - '700'
            - '800'
            - '900'
            - null
          description: Weight.
        style:
          type:
            - string
            - 'null'
          title: Style
          default: normal
          enum:
            - normal
            - italic
            - null
          description: Style.
      required:
        - file
      additionalProperties: true
  responses:
    BadRequest:
      description: 'The request is not valid: `message` says what to change.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    Unauthorized:
      description: The credential is missing or not accepted.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    Forbidden:
      description: The caller may not do this.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    NotFound:
      description: Nothing matches, or the caller may not see it.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    InternalServerError:
      description: 'The site failed: `message` is the generic “An error occurred.”'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Paste your API key as the CMS showed it: `fsk_<site>_<key id>_<secret>`
        (issued under API Keys). `ApiKey ` in front of it works too. Leave it
        empty to read as the public.
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        A person’s bearer token, from **Signing in (people)** → `POST
        /@apostrophecms/login/login`. Apps use an API key instead.

````

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