PRIV ProtocolPRIV Docs
API Reference

Event Ingestion API

Track events from your server or application with the PRIV Protocol Events API.

Track events from your server or application. The events API supports both single events and batch ingestion.

Track Events

POST/api/v1/events

Track one or more events. Supports two formats: the events array format and the SDK batch format.

Events Array Format

Use this format for server-side event tracking:

{
  "events": [
    {
      "event_type": "track",
      "event_name": "purchase_completed",
      "user_id": "user_123",
      "anonymous_id": "anon_456",
      "session_id": "sess_789",
      "properties": {
        "product_id": "prod_abc",
        "price": 99.99,
        "currency": "USD"
      },
      "page_url": "https://example.com/checkout",
      "page_title": "Checkout",
      "referrer": "https://example.com/cart",
      "timestamp": "2024-01-15T10:30:00Z",
      "consent_given": true
    }
  ]
}

SDK Batch Format

The @priv/sdk uses this format for automatic batching:

{
  "batch": [
    {
      "type": "track",
      "id": "evt_unique_id",
      "timestamp": "2024-01-15T10:30:00.000Z",
      "anonymousId": "anon_456",
      "sessionId": "sess_789",
      "event": "button_click",
      "properties": {
        "button": "cta_signup",
        "page": "/pricing"
      },
      "userId": "user_123"
    },
    {
      "type": "page",
      "id": "evt_page_id",
      "timestamp": "2024-01-15T10:29:00.000Z",
      "anonymousId": "anon_456",
      "sessionId": "sess_789",
      "name": "Pricing Page",
      "properties": {
        "url": "https://example.com/pricing",
        "title": "Pricing - Example"
      }
    },
    {
      "type": "identify",
      "id": "evt_identify_id",
      "timestamp": "2024-01-15T10:28:00.000Z",
      "anonymousId": "anon_456",
      "sessionId": "sess_789",
      "userId": "user_123",
      "traits": {
        "email": "user@example.com",
        "plan": "pro"
      }
    }
  ]
}

Event Types

TypeDescription
trackCustom event tracking
page_view / pagePage view event
identifyUser identification

Request Fields (Events Format)

FieldTypeRequiredDescription
event_typestringYesOne of: track, page_view, identify
event_namestringYesName of the event
user_idstringNoAuthenticated user identifier
anonymous_idstringNoAnonymous identifier
session_idstringNoSession identifier
propertiesobjectNoEvent properties/metadata
page_urlstringNoURL where event occurred
page_titlestringNoPage title
referrerstringNoReferring URL
timestampstringNoISO 8601 timestamp
consent_givenbooleanNoWhether user consented

One of user_id or anonymous_id is required to identify the event source.

Response

{
  "success": true,
  "data": {
    "received": 3,
    "stored": 3
  }
}

Limits

  • Maximum 100 events per batch request
  • Maximum 1MB payload size
  • Events older than 7 days may be rejected

Example: cURL

curl -X POST https://api.priv.io/v1/events \
  -H "Authorization: Bearer pk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_type": "track",
        "event_name": "swap_completed",
        "user_id": "user_123",
        "properties": {
          "token_in": "ETH",
          "token_out": "USDC",
          "amount": "1.5"
        },
        "consent_given": true
      }
    ]
  }'

Example: JavaScript

const response = await fetch('https://api.priv.io/v1/events', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer pk_live_xxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    events: [
      {
        event_type: 'track',
        event_name: 'purchase_completed',
        user_id: 'user_123',
        properties: {
          product_id: 'prod_abc',
          price: 99.99,
        },
        consent_given: true,
      },
    ],
  }),
});

const data = await response.json();
console.log(`Stored ${data.data.stored} events`);

Identify User

POST/api/v1/identify

Associate traits with a user. This creates or updates the user profile.

Request

{
  "userId": "user_123",
  "anonymousId": "anon_456",
  "traits": {
    "email": "user@example.com",
    "name": "John Doe",
    "plan": "pro",
    "created_at": "2024-01-01"
  }
}

Parameters

FieldTypeRequiredDescription
userIdstringYesUser identifier
anonymousIdstringNoPrevious anonymous ID to merge
traitsobjectNoUser traits/properties

Response

{
  "success": true,
  "data": {
    "userId": "user_123"
  }
}

Track Page View

POST/api/v1/page

Track a page view event with URL and referrer information.

Request

{
  "userId": "user_123",
  "name": "Pricing Page",
  "properties": {
    "url": "https://example.com/pricing",
    "title": "Pricing - Example",
    "referrer": "https://google.com"
  }
}

Response

{
  "success": true,
  "data": {
    "eventId": "evt_page_123"
  }
}

Best Practices

Event Naming

Use snake_case and be descriptive:

// Good
purchase_completed
button_clicked
form_submitted
swap_executed

// Bad
Purchase
click
submit

Properties

Include relevant context without sensitive data:

{
  "event": "swap_completed",
  "properties": {
    "token_in": "ETH",
    "token_out": "USDC",
    "amount_in": "1.5",
    "amount_out": "2500",
    "slippage": "0.5%",
    "dex": "uniswap"
  }
}

Timestamps

Always include accurate timestamps for historical data:

{
  "event_name": "order_completed",
  "timestamp": "2024-01-15T10:30:00.000Z"
}

Always track user consent status:

{
  "event_name": "page_view",
  "consent_given": true
}

Events without consent_given: true may be filtered out depending on your compliance settings.

Batching

For high-volume applications, batch events:

// Collect events
const eventQueue: Event[] = [];

// Send in batches of 50
if (eventQueue.length >= 50) {
  await sendEvents(eventQueue);
  eventQueue.length = 0;
}