OpenPanel

Track

This guide demonstrates how to interact with the OpenPanel API using cURL. These examples provide a low-level understanding of the API endpoints and can be useful for testing or for integrations where a full SDK isn't available.

Good to know

  • If you want to track geo location you'll need to pass the ip property as a header x-client-ip
  • If you want to track device information you'll need to pass the user-agent property as a header user-agent

Authentication

All requests to the OpenPanel API require authentication. You'll need to include your clientId and clientSecret in the headers of each request.

-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET"

Usage

Base URL

All API requests should be made to:

https://api.openpanel.dev

Tracking Events

To track an event:

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "track",
  "payload": {
    "name": "my_event",
    "properties": {
      "foo": "bar"
    }
  }
}'

Identifying Users

To identify a user:

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "identify",
  "payload": {
    "profileId": "123",
    "firstName": "Joe",
    "lastName": "Doe",
    "email": "joe@doe.com",
    "properties": {
      "tier": "premium"
    }
  }
}'

Incrementing Properties

To increment a numeric property:

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "increment",
  "payload": {
    "profileId": "1",
    "property": "visits",
    "value": 1
  }
}'

Decrementing Properties

To decrement a numeric property:

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "decrement",
  "payload": {
    "profileId": "1",
    "property": "visits",
    "value": 1
  }
}'

Creating or updating a group

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "group",
  "payload": {
    "id": "org_acme",
    "type": "company",
    "name": "Acme Inc",
    "properties": {
      "plan": "enterprise",
      "seats": 25
    }
  }
}'
FieldTypeRequiredDescription
idstringYesUnique identifier for the group
typestringYesCategory of group (e.g. "company", "workspace")
namestringYesDisplay name
propertiesobjectNoCustom metadata

Assigning a user to a group

Links a profile to one or more groups. This updates the profile record but does not auto-attach groups to future events — you still need to pass groups explicitly on each track call.

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "assign_group",
  "payload": {
    "profileId": "user_123",
    "groupIds": ["org_acme"]
  }
}'
FieldTypeRequiredDescription
profileIdstringNoProfile to assign. Falls back to the device ID if omitted
groupIdsstring[]YesGroup IDs to link to the profile

Tracking events with groups

Groups are never auto-populated on events — even if the profile has been assigned to a group via assign_group. Pass groups on every track event where you want group data.

curl -X POST https://api.openpanel.dev/track \
-H "Content-Type: application/json" \
-H "openpanel-client-id: YOUR_CLIENT_ID" \
-H "openpanel-client-secret: YOUR_CLIENT_SECRET" \
-d '{
  "type": "track",
  "payload": {
    "name": "report_exported",
    "profileId": "user_123",
    "groups": ["org_acme"],
    "properties": {
      "format": "pdf"
    }
  }
}'

Unlike the SDK, where setGroup() stores group IDs on the instance and attaches them to every subsequent track() call, the API has no such state. You must pass groups on each event.

Error Handling

The API uses standard HTTP response codes to indicate the success or failure of requests. In case of an error, the response body will contain more information about the error. Example error response:

{
  "error": "Invalid client credentials",
  "status": 401
}

Rate Limiting

The API implements rate limiting to prevent abuse. If you exceed the rate limit, you'll receive a 429 (Too Many Requests) response. The response will include headers indicating your rate limit status.

Best Practices

  1. Always use HTTPS to ensure secure communication.
  2. Store your clientId and clientSecret securely and never expose them in client-side code.
  3. Implement proper error handling in your applications.
  4. Respect rate limits and implement exponential backoff for retries.

On this page