# Events

Send server-side events for anything the browser cannot see: OAuth callbacks, payment webhooks, queue workers.

Source: https://sourceloop.ai/help/api/events/

---

| Endpoint | Method | Path | Permission |
| --- | --- | --- | --- |
| Send events | POST | `/v1/events` | `events:write` |

Base URL: `https://app.sourceloop.ai/api/v1`

## Send events

`POST /v1/events`

Send server-side events

Requires scope: `events:write`

For anything the browser cannot see: OAuth callbacks, payment webhooks, queue
workers. Events are validated and classified with exactly the same rules the
browser tracker applies, so a server-side conversion attributes identically.

Each event needs an email, a phone, or an `anonymous_id` to be attributable.
Read `_sl_aid` from the visitor's cookie and pass it as `anonymous_id` to
stitch a backend event to their browsing history.

Partial success: one malformed event does not discard the batch.

### Headers

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string | no |  |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `website` | string | no |  |
| `events` | object[] | yes |  |

### Request body: Event

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `events[].event_type` | string | no |  |
| `events[].event_name` | string | no |  |
| `events[].occurred_at` | string (date-time) | no |  |

### Request body: Identity

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `events[].email` | string | no |  |
| `events[].phone` | string | no |  |
| `events[].anonymous_id` | string | no | The visitor's _sl_aid cookie value. |

### Request body: Value

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `events[].revenue` | number | no |  |
| `events[].currency` | string | no |  |
| `events[].properties` | object | no |  |

### Responses

- `200` Accepted and rejected counts
- `400` Something was wrong with the request or the credential.
- `429` Too many requests for this workspace in the current minute. Wait Retry-After seconds and repeat the request unchanged.

### Example (cURL)

```bash
curl -s -X POST "https://app.sourceloop.ai/api/v1/events" \
  -H "Authorization: Bearer $SOURCELOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_type": "custom",
        "event_name": "signup_completed",
        "email": "jane@acme.com",
        "anonymous_id": "a1b2c3"
      }
    ]
  }'
```

### Example (Node)

```javascript
const res = await fetch(
  "https://app.sourceloop.ai/api/v1/events",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SOURCELOOP_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "events": [
        {
          "event_type": "custom",
          "event_name": "signup_completed",
          "email": "jane@acme.com",
          "anonymous_id": "a1b2c3"
        }
      ]
    }),
  },
);

const data = await res.json();
```

### Example (Python)

```python
import os, requests

res = requests.post(
    "https://app.sourceloop.ai/api/v1/events",
    headers={"Authorization": f"Bearer {os.environ['SOURCELOOP_API_KEY']}"},
    json={
      "events": [
        {
          "event_type": "custom",
          "event_name": "signup_completed",
          "email": "jane@acme.com",
          "anonymous_id": "a1b2c3"
        }
      ]
    },
)
data = res.json()
```
