> ## 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.

# Consultar una pulsera

> Saldo y estado de una pulsera a partir de su código NFC o UHF, junto con la entrada de la que salió.



## OpenAPI

````yaml /openapi.json get /wristbands/{code}
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}:
    get:
      tags:
        - Cashless
      summary: Consultar una pulsera
      description: >-
        Saldo y estado de una pulsera a partir de su código NFC o UHF, junto con
        la entrada de la que salió.
      parameters:
        - schema:
            type: string
          in: path
          name: code
          required: true
          description: Código NFC o UHF de la pulsera.
      responses:
        '200':
          description: La pulsera solicitada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Wristband'
        '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:
    Wristband:
      type: object
      properties:
        object:
          type: string
          enum:
            - wristband
        id:
          type: string
        nfc:
          type:
            - 'null'
            - string
        uhf:
          type:
            - 'null'
            - string
        status:
          type: string
          enum:
            - active
            - blocked
            - lost
            - released
            - pending_review
          description: >-
            `pending_review` significa que hay dos pulseras compitiendo por la
            misma entrada y nadie lo ha resuelto todavía.
        balance:
          type: integer
          description: Saldo en céntimos. Puede ser negativo tras una venta sin cobertura.
        attendee:
          type:
            - 'null'
            - object
          properties:
            name:
              type:
                - 'null'
                - string
            anonymous:
              type: boolean
        ticket:
          type:
            - 'null'
            - object
          properties:
            code:
              type:
                - 'null'
                - string
            ticket_type:
              type:
                - 'null'
                - string
        allowed_zones:
          type: array
          items:
            type: object
            properties:
              id:
                type:
                  - 'null'
                  - string
              name:
                type:
                  - 'null'
                  - string
            required:
              - id
              - name
            description: Zona permitida.
        valid_days:
          type: array
          items:
            type:
              - 'null'
              - string
        created_at:
          type:
            - 'null'
            - string
        updated_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.

````