---
title: Events (Write)
description: POST /v1/events - Track events from your backend
url: https://www.supalytics.co/docs/api/server-side-events
---



Track events from your server when client-side tracking isn't available.

## Endpoint

```
POST https://api.supalytics.co/v1/events
```

## Request

### Headers

| Header          | Value               |
| --------------- | ------------------- |
| `Authorization` | `Bearer sly_xxx...` |
| `Content-Type`  | `application/json`  |

### Body

| Field        | Type   | Required | Description                                                         |
| ------------ | ------ | -------- | ------------------------------------------------------------------- |
| `name`       | string | Yes      | Event name. Lowercase, numbers, underscores, hyphens. Max 64 chars. |
| `visitor_id` | string | No       | Visitor ID for attribution.                                         |
| `metadata`   | object | No       | Custom data. Max 10 keys, values max 255 chars.                     |

### Example

```bash
curl -X POST https://api.supalytics.co/v1/events \
  -H "Authorization: Bearer sly_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "subscription_created",
    "visitor_id": "abc123",
    "metadata": {
      "plan": "pro",
      "amount": 29
    }
  }'
```

## Response

### Success (200)

```json
{ "success": true }
```

## Visitor ID

The `visitor_id` is optional. Pass it when you have it to enable revenue attribution, funnels, and visitor filtering. Skip it for backend-only events (cron jobs, webhooks) where there's no user context.

### Option 1: Use stored visitor ID

If you store visitor IDs when users sign up, use that:

```javascript
// At signup (client-side), save the visitor ID
const visitorId = window.supalytics?.visitorId;
// Store this in your database with the user

// Later (server-side), use the stored ID
await fetch("https://api.supalytics.co/v1/events", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUPALYTICS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "upgraded",
    visitor_id: user.storedVisitorId,
    metadata: { plan: "enterprise" },
  }),
});
```

### Option 2: Pass from client

If the user is currently on your site, pass the visitor ID from client to server:

```javascript
// Client-side: send visitor ID with your API request
const visitorId = window.supalytics?.visitorId;

await fetch("/api/upgrade", {
  method: "POST",
  body: JSON.stringify({
    plan: "pro",
    visitorId, // pass to your backend
  }),
});
```

```javascript
// Server-side: use the passed visitor ID
export async function POST(req) {
  const { plan, visitorId } = await req.json();

  // Your upgrade logic...

  await fetch("https://api.supalytics.co/v1/events", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SUPALYTICS_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "upgraded",
      visitor_id: visitorId,
      metadata: { plan },
    }),
  });
}
```

### Option 3: No visitor ID

For backend-only events (cron jobs, webhooks without user context), omit the visitor ID:

```javascript
await fetch("https://api.supalytics.co/v1/events", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUPALYTICS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "daily_report_sent",
    metadata: { recipients: 150 },
  }),
});
```

## Rate Limits

* **100 requests per second** per API key
* Rate limit headers in response: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`


---

## Other Documentation

- [Autocapture](https://www.supalytics.co/llms/docs/autocapture)
- [Backfill Existing Subscriptions](https://www.supalytics.co/llms/docs/backfill-existing-subscriptions)
- [Block Your Own Traffic](https://www.supalytics.co/llms/docs/block-your-traffic)
- [CLI](https://www.supalytics.co/llms/docs/cli)
- [Custom Events](https://www.supalytics.co/llms/docs/custom-events)
- [Features](https://www.supalytics.co/llms/docs/features)
- [Conversion Funnels](https://www.supalytics.co/llms/docs/funnels)
- [Introduction](https://www.supalytics.co/llms/docs)
- [Install Script](https://www.supalytics.co/llms/docs/install-script)
- [MRR Tracking](https://www.supalytics.co/llms/docs/mrr-tracking)
- [Revenue Attribution](https://www.supalytics.co/llms/docs/revenue-attribution)
- [Agent Skills](https://www.supalytics.co/llms/docs/skills)
- [Tracking Modes](https://www.supalytics.co/llms/docs/tracking-modes)
- [Visitor Journey](https://www.supalytics.co/llms/docs/visitor-journey)
- [Annotations](https://www.supalytics.co/llms/docs/api/annotations)
- [Error Codes](https://www.supalytics.co/llms/docs/api/errors)
- [Events (Read)](https://www.supalytics.co/llms/docs/api/events)
- [API Reference](https://www.supalytics.co/llms/docs/api)
- [Journeys](https://www.supalytics.co/llms/docs/api/journeys)
- [Query API](https://www.supalytics.co/llms/docs/api/query)
- [Realtime API](https://www.supalytics.co/llms/docs/api/realtime)
- [Revenue Attribution API](https://www.supalytics.co/llms/docs/api/revenue-attribution)