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

# Introduction

> What you can do with the VENTRY API and how it is organised.

VENTRY is an event management platform: ticketing, door accreditation, zone
control and cashless payment by wristband. This API lets an external system
integrate with all of it.

## What it is for

<CardGroup cols={2}>
  <Card title="Push tickets" icon="ticket" href="/en/guides/import-tickets">
    You sell tickets on your platform and register them in VENTRY so they work
    for accreditation at the door.
  </Card>

  <Card title="Accredit attendees" icon="id-card" href="/en/guides/accreditation">
    Your application scans the QR and the wristband; VENTRY does the redemption.
  </Card>

  <Card title="Read balances" icon="wallet" href="/en/guides/cashless">
    Wristband balances, purchases and top-ups.
  </Card>

  <Card title="Sync data" icon="arrows-rotate" href="/en/pagination">
    Dump sales and access logs into your own data warehouse.
  </Card>
</CardGroup>

## One deployment, one event

Each VENTRY installation corresponds to **a single event**. Your API key already
determines which event that is, which is why no endpoint takes an event
identifier: the base URL the organiser gives you is theirs.

Within that event, your key may additionally be restricted to certain ticket
types or certain days. Anything outside that scope behaves as if it did not
exist — it returns `404`, not `403` — so do not be alarmed if you cannot see
tickets the organiser can.

## The data model, in a minute

<Steps>
  <Step title="Event">
    It has **days** (`Day`) and **zones** (`Zone`). Almost everything else hangs
    off a day.
  </Step>

  <Step title="Tickets">
    A **ticket** (`Ticket`) has a **type** (`TicketType`), which defines which
    zones it grants access to and which items it includes, plus a list of days it
    is valid for.
  </Step>

  <Step title="Accreditation">
    At the door, the ticket is **redeemed** for a physical **wristband**
    (`Wristband`). From then on, the wristband is the attendee's identity inside
    the venue.
  </Step>

  <Step title="Cashless">
    The wristband carries **balance**. It is **topped up** and spent on
    **purchases** (`transaction`) at the bars.
  </Step>
</Steps>

## Conventions

|                 |                                                                           |
| --------------- | ------------------------------------------------------------------------- |
| **Amounts**     | Integers in **cents**. `1250` is €12.50. The currency is in `GET /event`. |
| **Dates**       | ISO 8601 in UTC. The event's time zone is in `GET /event`.                |
| **Identifiers** | 24-character hexadecimal strings.                                         |
| **Fields**      | `snake_case`.                                                             |

### `occurred_at` versus `created_at`

VENTRY terminals keep charging when connectivity drops and sync when it comes
back. That is why sales and top-ups carry **two** timestamps:

* `occurred_at` — when it actually happened.
* `created_at` — when it reached the server.

<Warning>
  To group by time or reconcile takings you must always use **`occurred_at`**.
  A sale made at 22:00 and synced at 02:00 belongs to Friday night, not Saturday's.
  If you group by `created_at`, one day's takings will appear split across two.
</Warning>

## First call

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.ventry.es/v1/ping \
    -H "Authorization: Bearer $VENTRY_KEY"
  ```

  ```js Node.js theme={null}
  const response = await fetch("https://api.ventry.es/v1/ping", {
    headers: { Authorization: `Bearer ${process.env.VENTRY_KEY}` },
  });

  console.log(await response.json());
  ```

  ```python Python theme={null}
  import os, requests

  response = requests.get(
      "https://api.ventry.es/v1/ping",
      headers={"Authorization": f"Bearer {os.environ['VENTRY_KEY']}"},
      timeout=10,
  )

  print(response.json())
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init("https://api.ventry.es/v1/ping");
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("VENTRY_KEY")],
  ]);

  $response = json_decode(curl_exec($ch), true);
  curl_close($ch);

  print_r($response);
  ```
</CodeGroup>

```json theme={null}
{
  "object": "ping",
  "key": {
    "id": "6a3d04709bcd4477a1bfe4b3",
    "name": "TicketRadar production",
    "prefix": "vk_live_8Kq2Zx",
    "scopes": ["event.read", "tickets.read", "tickets.write"]
  },
  "restrictions": { "ticket_types": [], "days": [] },
  "event": {
    "name": "Sample Event 2026",
    "currency": "EUR",
    "timezone": "Europe/Madrid"
  }
}
```

`restrictions` with empty lists means your key sees the whole event.
