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

# List published products and bundles

> Returns published catalog items. Use `id` + `type` when creating an order
(`product_id` or `bundle_id`).




## OpenAPI

````yaml /openapi.yaml get /products
openapi: 3.1.0
info:
  title: Kawan Digital Public API
  version: 1.0.0
  summary: Store-scoped Order API
  description: >
    External systems can create and read **store orders** using API keys, and

    receive lifecycle events via signed webhooks.


    - **Access:** Growth and Scale stores only

    - **Auth:** `Authorization: Bearer {API_KEY}`

    - **Manage keys / webhooks:** [Dashboard → Developer
    API](https://kawan.digital/dashboard/settings/developers)

    - **Tutorial:** [Integrasi API](/integrasi)

    - **Webhooks:** [Dokumentasi webhook](/webhooks)

    - **Docs hub:** [Ringkasan](/)


    All JSON responses use `{ "success": true, "data": … }` or

    `{ "success": false, "error": { "code", "message" } }`.


    Amounts are IDR integers. Keys are scoped to **one store**.
  contact:
    name: Kawan Digital
    email: halo@kawan.digital
    url: https://kawan.digital/kontak
servers:
  - url: https://api.kawan.digital/v1
    description: Production
  - url: http://api.lvh.me:3000/v1
    description: Local (requires NEXT_PUBLIC_ROOT_DOMAIN=lvh.me)
security:
  - bearerAuth: []
tags:
  - name: Catalog
    description: Published products and bundles for the authenticated store.
  - name: Payments
    description: Checkout methods available for the store.
  - name: Orders
    description: Create and read store orders.
  - name: Webhooks
    description: |
      Signed HTTPS callbacks for order lifecycle events.
      See [Webhook documentation](/webhooks).
paths:
  /products:
    get:
      tags:
        - Catalog
      summary: List published products and bundles
      description: >
        Returns published catalog items. Use `id` + `type` when creating an
        order

        (`product_id` or `bundle_id`).
      operationId: listProducts
      parameters:
        - $ref: '#/components/parameters/Offset'
        - $ref: '#/components/parameters/Limit'
      responses:
        '200':
          description: Catalog page
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductListResponse'
              example:
                success: true
                data:
                  items:
                    - id: 11111111-1111-4111-8111-111111111111
                      type: product
                      title: Ebook Starter
                      slug: ebook-starter
                      price: 99000
                      status: published
                  has_more: false
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/PlanRequired'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    Offset:
      in: query
      name: offset
      schema:
        type: integer
        minimum: 0
        default: 0
    Limit:
      in: query
      name: limit
      schema:
        type: integer
        minimum: 1
        maximum: 50
        default: 20
  schemas:
    ProductListResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          const: true
        data:
          type: object
          required:
            - items
            - has_more
          properties:
            items:
              type: array
              items:
                $ref: '#/components/schemas/CatalogItem'
            has_more:
              type: boolean
    CatalogItem:
      type: object
      required:
        - id
        - type
        - title
        - slug
        - price
        - status
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - product
            - bundle
        title:
          type: string
        slug:
          type: string
        price:
          type: integer
          description: IDR
        status:
          type: string
    ErrorEnvelope:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - INVALID_REQUEST
                - UNAUTHORIZED
                - FORBIDDEN
                - PLAN_REQUIRED
                - NOT_FOUND
                - CONFLICT
                - RATE_LIMITED
                - INTERNAL_ERROR
            message:
              type: string
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            success: false
            error:
              code: UNAUTHORIZED
              message: Missing or invalid Authorization header.
    PlanRequired:
      description: Public API is not on this store's plan
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            success: false
            error:
              code: PLAN_REQUIRED
              message: Public API is not available on this store's plan.
    RateLimited:
      description: Rate limit exceeded (Retry-After header)
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds until the client may retry.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            success: false
            error:
              code: RATE_LIMITED
              message: Rate limit exceeded.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key from Dashboard → Developer API. Shown once when created.

````