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

# bulkEvent()

> Ingest up to 500 events in a single API call.

## Overview

`bulkEvent()` sends a batch of events in one HTTP request. Use it for backfills, importing historical data, or batching events you've already collected server-side.

For ongoing high-frequency tracking, use the [EventBatcher](/churnkit/events/batcher) which handles buffering automatically.

## Signature

```typescript theme={null}
churn.bulkEvent(
  events: BulkEventItem[],
  options?: CallOptions
): Promise<{ ok: boolean; accepted: number }>
```

## Parameters

<ParamField path="events" type="BulkEventItem[]" required>
  Array of event objects. Maximum 500 items per call.
</ParamField>

<ParamField path="options.signal" type="AbortSignal">
  Cancel the request.
</ParamField>

## BulkEventItem

```typescript theme={null}
interface BulkEventItem {
  userId: string
  event: string
  properties?: EventProperties   // optional key-value metadata
  timestamp?: string             // ISO 8601 — defaults to server time if omitted
}
```

## Examples

### Backfill historical events

```typescript theme={null}
const events = historicalData.map((row) => ({
  userId: row.user_id,
  event: row.event_name,
  properties: row.metadata,
  timestamp: row.created_at,
}))

const { accepted } = await churn.bulkEvent(events)
console.log(`Accepted ${accepted} events`)
```

### Batch events collected in memory

```typescript theme={null}
const buffer: BulkEventItem[] = []

function trackLater(userId: string, event: string, props?: Record<string, unknown>) {
  buffer.push({ userId, event, properties: props })
}

// Flush every minute
setInterval(async () => {
  if (buffer.length === 0) return
  const batch = buffer.splice(0, 500)
  await churn.bulkEvent(batch)
}, 60_000)
```

### Chunking large datasets

```typescript theme={null}
const CHUNK_SIZE = 500

async function backfill(allEvents: BulkEventItem[]) {
  for (let i = 0; i < allEvents.length; i += CHUNK_SIZE) {
    const chunk = allEvents.slice(i, i + CHUNK_SIZE)
    await churn.bulkEvent(chunk)
    console.log(`Flushed events ${i}–${i + chunk.length}`)
  }
}
```

## Return value

```typescript theme={null}
{
  ok: true,
  accepted: 247   // number of events successfully ingested
}
```

## Limits

| Limit               | Value |
| ------------------- | ----- |
| Max events per call | 500   |
| Max payload size    | 1 MB  |

## Errors

| Code                | When                                     |
| ------------------- | ---------------------------------------- |
| `VALIDATION_ERROR`  | Array is empty or contains invalid items |
| `PAYLOAD_TOO_LARGE` | More than 500 events                     |
| `RATE_LIMITED`      | Too many bulk calls                      |
| `TIMEOUT`           | Request exceeded timeout                 |
