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

# Empujar productos

> Alta, modificación o baja de productos, en lote. Idempotente por `event_id`;
los eventos más viejos que lo ya aplicado se descartan (`skipped_stale`);
un ítem inválido no rechaza el lote (`rejected` por ítem).

`action: "delete"` desactiva los productos listados (no se borran: los
pedidos históricos siguen siendo legibles).




## OpenAPI

````yaml /openapi-pos.yaml post /v1/catalog/items
openapi: 3.1.0
info:
  title: Xenda POS Bridge
  version: 1.0.0
  description: >
    Bridge entre tu sistema de punto de venta y el módulo de pedidos por
    WhatsApp de

    Xenda. Tu POS empuja el catálogo, consulta los pedidos que toma el bot e
    informa

    los cambios de estado. Todo el tráfico lo origina tu sistema; la key es por

    sucursal.
servers:
  - url: https://api.automationhub.one/api:07fkGLk_
    description: Producción (sandbox = misma URL con key de la sucursal demo)
security:
  - ApiKeyAuth: []
paths:
  /v1/catalog/items:
    post:
      summary: Empujar productos
      description: >
        Alta, modificación o baja de productos, en lote. Idempotente por
        `event_id`;

        los eventos más viejos que lo ya aplicado se descartan
        (`skipped_stale`);

        un ítem inválido no rechaza el lote (`rejected` por ítem).


        `action: "delete"` desactiva los productos listados (no se borran: los

        pedidos históricos siguen siendo legibles).
      operationId: pushCatalogItems
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CatalogItemsRequest'
            example:
              event_id: pos-evt-20260730-001
              occurred_at: '2026-07-30T13:00:00-03:00'
              action: upsert
              items:
                - codigo: '1001'
                  nombre: Kilo de helado
                  categoria: Helados
                  precio: 16000
                  deshabilitado: false
      responses:
        '200':
          description: >-
            Resultado del lote (o replay idempotente si el `event_id` ya se
            procesó).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IngestResponse'
        '403':
          $ref: '#/components/responses/AccessDenied'
components:
  schemas:
    CatalogItemsRequest:
      type: object
      required:
        - event_id
        - occurred_at
        - items
      properties:
        event_id:
          type: string
          description: >-
            ID único del evento en tu sistema. Reintentar con el mismo
            `event_id` es seguro.
        occurred_at:
          type: string
          format: date-time
          description: >-
            Cuándo ocurrió el cambio en tu sistema. Define el orden entre
            eventos.
        store_id:
          type: integer
          description: >-
            Opcional. Verificación cruzada contra la sucursal de la key (403 si
            no coincide).
        action:
          type: string
          enum:
            - upsert
            - delete
          default: upsert
        items:
          type: array
          items:
            $ref: '#/components/schemas/CatalogItem'
    IngestResponse:
      type: object
      properties:
        duplicate:
          type: boolean
          description: >-
            `true` si el `event_id` ya se había procesado (no se reprocesó
            nada).
        accepted:
          type: integer
        skipped_stale:
          type: integer
          description: Ítems descartados por ser más viejos que lo ya aplicado.
        rejected:
          type: array
          items:
            type: object
            properties:
              codigo:
                type: string
              error:
                type: string
    CatalogItem:
      type: object
      required:
        - codigo
      properties:
        codigo:
          type: string
          description: Tu ID estable del producto. `nombre` es obligatorio en `upsert`.
        nombre:
          type: string
        categoria:
          type: string
        precio:
          type: number
        deshabilitado:
          type: boolean
          default: false
        max_opciones:
          type: integer
          description: >
            Opcional — cuántas opciones admite el producto (ej. 4 sabores en un
            kilo).

            Si tu sistema no maneja este dato, se configura desde la plataforma
            Xenda.
    Error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        payload: {}
  responses:
    AccessDenied:
      description: Key inválida, inactiva o `store_id` que no corresponde a la key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: ERROR_CODE_ACCESS_DENIED
            message: Invalid API key.
            payload: ''
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Key por sucursal provista por Xenda (formato `xnd_...`).

````