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

# Consumiciones de una pulsera

> Ventas cobradas contra el saldo de una pulsera concreta.



## OpenAPI

````yaml /openapi.json get /wristbands/{code}/transactions
openapi: 3.1.0
info:
  title: VENTRY API
  version: 1.0.0
  description: >-
    API pública de **VENTRY** para integradores externos.


    Permite volcar entradas desde una plataforma de ticketing, acreditar
    asistentes

    desde una aplicación propia y consultar el estado del evento en tiempo real.


    ## Autenticación


    Todas las llamadas viajan con una API key en la cabecera `Authorization`:


    ```

    Authorization: Bearer vk_live_8Kq2...

    ```


    La clave se genera desde el panel de VENTRY y **se muestra una sola vez**.
    Si se

    pierde, hay que emitir otra. Las claves que piden permisos de escritura
    nacen

    desactivadas y necesitan que un administrador del evento las habilite a
    mano.


    ## Un despliegue, un evento


    Cada instalación de VENTRY corresponde a **un único evento**. La API key ya

    determina de qué evento se está hablando, por eso ningún endpoint pide un

    identificador de evento. Una clave puede además estar limitada a ciertos
    tipos

    de entrada o a ciertos días: lo que quede fuera de ese ámbito se comporta
    como

    si no existiera.


    ## Convenciones


    - **Importes**: enteros en **céntimos**. `1250` son 12,50 €. La moneda está
    en `GET /event`.

    - **Fechas**: ISO 8601 en UTC. El huso horario del evento está en `GET
    /event`.

    - **Identificadores**: cadenas de 24 caracteres hexadecimales.

    - **Campos**: `snake_case`.


    ### `occurred_at` frente a `created_at`


    Los terminales de VENTRY siguen cobrando sin cobertura y sincronizan
    después.

    Por eso las ventas y recargas llevan dos marcas: `occurred_at` es cuándo
    pasó

    de verdad y `created_at` cuándo llegó al servidor. **Para agrupar por tiempo
    o

    cuadrar caja hay que usar siempre `occurred_at`**; una venta de las 22:00

    sincronizada a las 02:00 pertenece a la noche del viernes, no a la del
    sábado.


    ## Paginación


    Los listados devuelven `{ object: "list", data, has_more, next_cursor }`.
    Para

    la siguiente página se repite la llamada con `starting_after=<next_cursor>`.

    No hay números de página: el cursor es estable aunque se sigan creando
    registros

    mientras se recorre el listado.


    Para sincronizar de forma incremental, combina `updated_since` con el
    cursor.


    ## Idempotencia


    Las escrituras exigen la cabecera `Idempotency-Key` con un UUID generado por

    el cliente. Repetir la misma llamada con la misma clave devuelve la
    respuesta

    original sin volver a ejecutar nada, así que un reintento tras un fallo de
    red

    nunca duplica una entrada ni una recarga. Reutilizar la clave con un cuerpo

    distinto devuelve `422 idempotency_key_reused`.


    ## Límites


    Por defecto **120 peticiones por minuto** y clave, y **20 por minuto** para
    las

    escrituras. Cada respuesta lleva `x-ratelimit-remaining` y, al agotarse,

    `retry-after` con los segundos que faltan.


    ## Errores


    Todos los errores comparten la misma forma y llevan un `request_id` que

    conviene registrar: con él, el soporte de VENTRY encuentra la petición
    exacta.
  contact:
    name: Soporte VENTRY
    url: https://ventry.es
servers:
  - url: http://localhost:3000/v1
    description: Servidor del evento
security:
  - apiKey: []
tags:
  - name: Evento
    description: >-
      Configuración del evento: días, zonas y tipos de entrada. Es lo primero
      que hay que leer para mapear el catálogo propio contra el de VENTRY.
  - name: Entradas
    description: >-
      Alta, consulta y anulación de entradas. El caso de uso principal de la
      API.
  - name: Accesos
    description: >-
      Acreditación en puerta y control de zonas. Requiere permisos de escritura
      activados manualmente.
  - name: Cashless
    description: >-
      Saldo de pulseras, consumiciones y recargas. Todos los importes en
      céntimos.
  - name: Informes
    description: Agregados de venta, coherentes con el cierre de caja del panel.
  - name: Meta
    description: Comprobación de credenciales y documentación.
paths:
  /wristbands/{code}/transactions:
    get:
      tags:
        - Cashless
      summary: Consumiciones de una pulsera
      description: Ventas cobradas contra el saldo de una pulsera concreta.
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          in: query
          name: limit
          required: false
          description: Número de elementos por página.
        - schema:
            type: string
          in: query
          name: starting_after
          required: false
          description: >-
            Cursor devuelto en `next_cursor` por la página anterior. Omítelo en
            la primera llamada.
        - schema:
            type: string
          in: query
          name: day
          required: false
          description: Id de día de `GET /days`.
        - schema:
            type: string
          in: query
          name: since
          required: false
          description: >-
            Fecha ISO 8601. Filtra por `occurred_at`, es decir por cuándo
            ocurrió de verdad la operación.
        - schema:
            type: string
          in: path
          name: code
          required: true
      responses:
        '200':
          description: Consumiciones de la pulsera.
          content:
            application/json:
              schema:
                type: object
                description: Consumiciones de la pulsera.
                properties:
                  object:
                    type: string
                    enum:
                      - list
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Transaction'
                  has_more:
                    type: boolean
                    description: >-
                      Si es `true`, pide la siguiente página con
                      `starting_after`.
                  next_cursor:
                    type:
                      - 'null'
                      - string
                    description: Valor a pasar en `starting_after` para continuar.
                required:
                  - object
                  - data
                  - has_more
                  - next_cursor
        '400':
          description: Petición mal formada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: API key ausente, inválida o caducada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: La API key no tiene el permiso necesario.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: El recurso no existe o está fuera del ámbito de la API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Se ha superado el límite de peticiones.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Error interno.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Transaction:
      type: object
      properties:
        object:
          type: string
          enum:
            - transaction
        id:
          type: string
        status:
          type: string
          enum:
            - pending
            - completed
            - failed
            - refunded
        type:
          type: string
          enum:
            - cart
            - custom
        payment_method:
          type: string
          enum:
            - wristband
            - card
        total:
          type: integer
          description: Total cobrado, en céntimos.
        total_base:
          type: integer
        total_tax:
          type: integer
        tax_breakdown:
          type: array
          items:
            type: object
            properties:
              tax_type:
                type: string
                enum:
                  - IVA
                  - IGIC
              rate:
                type: number
              base:
                type: integer
              amount:
                type: integer
        items:
          type: array
          items:
            type: object
            properties:
              product_id:
                type:
                  - 'null'
                  - string
              name:
                type:
                  - 'null'
                  - string
              quantity:
                type: integer
              unit_price:
                type: integer
              charged_amount:
                type: integer
                description: >-
                  Lo realmente cobrado al saldo. Difiere de `unit_price *
                  quantity` cuando parte se cubrió con consumiciones incluidas.
              included_quantity:
                type: integer
        wristband_id:
          type:
            - 'null'
            - string
        day_id:
          type:
            - 'null'
            - string
        device_id:
          type:
            - 'null'
            - string
        occurred_at:
          type:
            - 'null'
            - string
          description: >-
            Cuándo ocurrió de verdad. Una venta sin cobertura lleva aquí su hora
            real, no la de sincronización: es el campo con el que hay que
            agrupar por tiempo.
        created_at:
          type:
            - 'null'
            - string
    Error:
      type: object
      description: >-
        Todos los errores de la API comparten esta forma. Ramifica sobre `code`,
        que es estable; `message` puede cambiar de redacción.
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              enum:
                - authentication_error
                - permission_error
                - invalid_request_error
                - not_found_error
                - conflict_error
                - rate_limit_error
                - api_error
            code:
              type: string
              example: ticket_not_found
            message:
              type: string
            param:
              type: string
              description: Campo de la petición que provocó el error, si aplica.
            request_id:
              type: string
              description: Identificador de la petición. Cítalo al contactar con soporte.
              example: req_9f2c1a4e7b304d51
          required:
            - type
            - code
            - message
            - request_id
      required:
        - error
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: >-
        API key del integrador, emitida desde el panel de VENTRY. Formato
        `vk_live_...` en producción y `vk_test_...` en entornos de prueba.

````