Server API
Track events, identify visitors, and resolve user IDs from your backend. The Server API is designed for server-to-server communication and uses a separate secret key for authentication.
Overview
The Server API lets you send events and update visitor data from your backend, webhooks, or background jobs. Use it for:
- Tracking server-side events (payments, emails, webhooks)
- Updating visitor traits from your CRM or database
- Resolving browser visitor IDs to server-side user IDs
- Optionally attaching events to browser sessions
Base URL: https://app.himetrica.com/api/v1
Authentication
All Server API endpoints require a secret key passed in the X-API-Key header. Secret keys start with hm_sk_.
You can find your secret key in Project Settings under "Secret Key (Server API)". You can regenerate it at any time — the old key will stop working immediately.
Keep your secret key safe
Rate Limiting
Server API endpoints are rate-limited per secret key:
| Endpoint | Limit | Window |
|---|---|---|
POST /track | 1,000 requests | 1 minute |
POST /identify | 500 requests | 1 minute |
GET /user-id | 100 requests | 1 minute |
For the full breakdown of all rate limits including client-side tracking, per-visitor limits, plan quotas, and project suspension, see the Rate Limits page.
GET /user-id
Resolve a browser visitorId to a stable server-side userId. The visitor ID is the value stored in the browser by the tracker script.
Query Parameters
visitorId (required) — The browser visitor ID
curl -X GET "https://app.himetrica.com/api/v1/user-id?visitorId=abc123" \
-H "X-API-Key: hm_sk_your_secret_key"Response
{
"userId": "hm_usr_a1b2c3d4e5f6..."
}POST /track
Track a server-side custom event. The event will appear in your dashboard alongside browser-tracked events.
Request Body
userId, email, or visitorId (one required) — Identify the visitor
eventName (required) — Event name (letters, numbers, underscores, hyphens)
properties (optional) — Key-value pairs (max 10KB)
timestamp (optional) — ISO 8601 timestamp for backfilling
session (optional) — "latest", "new", or omit. See Session Attachment.
curl -X POST "https://app.himetrica.com/api/v1/track" \
-H "X-API-Key: hm_sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "hm_usr_a1b2c3d4e5f6",
"eventName": "subscription_renewed",
"properties": {
"plan": "pro",
"amount": 29.99,
"currency": "USD"
}
}'Track by email
You can use the visitor's email address instead of a userId or visitorId. The visitor must have been previously identified with that email.
curl -X POST "https://app.himetrica.com/api/v1/track" \
-H "X-API-Key: hm_sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"eventName": "invoice_paid",
"properties": {
"amount": 99.99,
"currency": "USD"
}
}'Response
202 Accepted with { "success": true }. The event is processed asynchronously.POST /identify
Update a visitor's traits (name, email, and custom properties) from your server.
Request Body
userId, email, or visitorId (one required) — Identify the visitor
traits (required) — Object with visitor properties
traits.userId — Optional. A stable external user ID for cross-device visitor merging.
traits.email — Visitor email
traits.name — Visitor name
traits.* — Any additional key-value pairs are stored as metadata
curl -X POST "https://app.himetrica.com/api/v1/identify" \
-H "X-API-Key: hm_sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "hm_usr_a1b2c3d4e5f6",
"traits": {
"userId": "usr_123",
"email": "jane@example.com",
"name": "Jane Doe",
"plan": "enterprise",
"company": "Acme Inc"
}
}'Session Attachment
By default, server-side events have no session. Use the session field to attach events to a browser session:
| Value | Behavior |
|---|---|
"latest" | Attach to the visitor's most recent browser session. If no session exists, the event is still created with no session. |
"new" | Create a new minimal session and attach the event to it. |
| omitted / null | No session (default). The event is recorded without a session. |
Attach to latest session
curl -X POST "https://app.himetrica.com/api/v1/track" \
-H "X-API-Key: hm_sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "hm_usr_a1b2c3d4e5f6",
"eventName": "email_opened",
"session": "latest",
"properties": {
"campaign": "onboarding_day_3"
}
}'Create a new session
curl -X POST "https://app.himetrica.com/api/v1/track" \
-H "X-API-Key: hm_sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"visitorId": "abc123",
"eventName": "webhook_received",
"session": "new",
"properties": {
"source": "stripe"
}
}'Error Handling
All errors return a JSON object with an error field.
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — missing or invalid secret key |
403 | Plan limit exceeded |
404 | Visitor not found |
429 | Rate limited — too many requests |
503 | Service temporarily unavailable |
Examples
Node.js / TypeScript
const API_URL = "https://app.himetrica.com/api/v1";
const SECRET_KEY = process.env.HIMETRICA_SECRET_KEY; // hm_sk_...
async function trackServerEvent(userId, eventName, properties = {}) {
const response = await fetch(`${API_URL}/track`, {
method: "POST",
headers: {
"X-API-Key": SECRET_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ userId, eventName, properties }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
return response.json();
}
// Example: track a server-side event
await trackServerEvent("hm_usr_abc123", "invoice_paid", {
amount: 99.99,
currency: "USD",
});Python
import requests
import os
API_URL = "https://app.himetrica.com/api/v1"
SECRET_KEY = os.environ["HIMETRICA_SECRET_KEY"] # hm_sk_...
def track_event(user_id: str, event_name: str, properties: dict = None):
response = requests.post(
f"{API_URL}/track",
headers={
"X-API-Key": SECRET_KEY,
"Content-Type": "application/json",
},
json={
"userId": user_id,
"eventName": event_name,
"properties": properties or {},
},
)
response.raise_for_status()
return response.json()
# Example
track_event("hm_usr_abc123", "subscription_renewed", {
"plan": "pro",
"amount": 29.99,
})