> Send custom events and query raw or aggregated event data from the SDKs

# Ingesting & Querying Events

The server client (`createPyloServer` / `createPyloNode`) exposes `ingestEvents` and an `events`
namespace. The hooks mirror both for Client Components.

## Ingest events

```typescript filename="example.ts"
await pylo.ingestEvents([
  {
    event_name: 'order.completed',
    properties: { order_id: 'o-1', total: 149.9 },
  },
]);
```

The server sets `ts` and prefixes the name to `custom.order.completed`.

In Client Components:

```typescript filename="example.ts"
const { mutateAsync } = pylo.usePyloIngestEvents();

await mutateAsync([
  { event_name: 'signup.viewed', properties: { plan: 'pro' } },
]);
```

## List raw events

```typescript filename="example.ts"
const result = await pylo.events.list({
  filter: {
    query: [{
      condition: { field: 'event_name', operator: 'equal', value: 'custom.order.completed' },
    }],
    sortby: [{ field: 'ts', order: 'desc' }],
  },
  pagination: { page: 1, per_page: 50 },
});
```

Filter fields are the top-level columns (`event_name`, `ts`, `source`) or dotted property paths like
`order.total`. Use `select_fields` to restrict the returned columns in list mode.

## Analytics mode

Set `dimensions` and `aggregate` to get grouped rows plus grand-total `aggregations` instead of raw
events. A dimension is either a field or a time bucket.

```typescript filename="example.ts"
const result = await pylo.events.list({
  filter: {
    dimensions: [
      { timeBucket: { interval: '1 day', timezone: 'Europe/Berlin' } },
      { field: 'plan' },
    ],
    aggregate: [
      { field: 'order.total', function: 'sum', alias: 'revenue' },
      { field: 'event_name', function: 'count', alias: 'orders' },
    ],
  },
});
```

The first dimension is the primary axis, the second the series breakdown.

The hook version is `usePyloEventList(options)` with the same options.

## Discovering properties

```typescript filename="example.ts"
// Property paths (and JSON types) present across recent events
const keys = await pylo.events.propertyKeys();

// Most frequent distinct values of one field, with counts
const values = await pylo.events.fieldValues('plan', { limit: 10 });
```

Hooks: `usePyloEventPropertyKeys(options)` and `usePyloEventFieldValues(field, options)`.
