Skip to content
IForevents Docs
IForevents Docs
InicioPanelGitHubPrivacidadTérminosSeguridadIntroducción
TrackingIdentify usersTrack events
Web (JavaScript)Flutter SDKJavaScript SDK (browser and Node.js)React, Next.js and React NativePython SDKGo SDKJava and Android SDKsSwift SDK (iOS, macOS)Ruby SDKPHP SDK.NET and Unity SDKsClient libraries (JavaScript, Python, Go)HTTP Ingest (Server-Side)
Soporte y SLA
TrackingSDKs

HTTP Ingest (Server-Side)

Send events from your backend with plain HTTP

Any language with an HTTP client can send events. Authenticate every request with the project key in the X-Project-Key header, name the person in X-User-Id, and send JSON.

Endpoints

MethodPathBodySuccess
POST/v1/events/track{"event_name", "event_type"?, "properties"?}201
POST/v1/events/batch{"events": [{"name", "type"?, "properties"?, "created_at"?}, ...]} (max 500)202
POST/v1/events/identify{"custom_id", "name"?, "email"?, "phone_number"?, "properties"?}201 with the user

X-User-Id is your id for the person (the same value identify takes as custom_id), any string up to 256 characters. Always send it from a server: every request from your backend arrives from the same address, and without the header the api would file all of them under one address-derived profile (why). For visitors you have not signed up yet, generate an id once per visitor (a cookie or session id works) and keep sending it.

curl

export IFOREVENTS_PROJECT_KEY="<project key>"

# track
curl -X POST https://api.iforevents.com/v1/events/track \
  -H "X-Project-Key: $IFOREVENTS_PROJECT_KEY" \
  -H "X-User-Id: user-123" \
  -H "Content-Type: application/json" \
  -d '{"event_name":"purchase","properties":{"amount":"99.99","currency":"USD"}}'

# identify (optional: profile details for the same id)
curl -X POST https://api.iforevents.com/v1/events/identify \
  -H "X-Project-Key: $IFOREVENTS_PROJECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"custom_id":"user-123","email":"[email protected]","properties":{"plan":"pro"}}'

Node.js

const key = process.env.IFOREVENTS_PROJECT_KEY;

async function track(userId, eventName, properties) {
  const res = await fetch("https://api.iforevents.com/v1/events/track", {
    method: "POST",
    headers: {
      "X-Project-Key": key,
      "X-User-Id": userId,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ event_name: eventName, properties }),
  });
  if (!res.ok) throw new Error(`iforevents ${res.status}: ${await res.text()}`);
}

// In a route handler: the signed-in user's id, or the visitor's session id.
await track(req.user?.id ?? req.session.id, "purchase", { amount: "99.99", currency: "USD" });

Python

import os
import requests

KEY = os.environ["IFOREVENTS_PROJECT_KEY"]
BASE = "https://api.iforevents.com"


def track(user_id: str, event_name: str, properties: dict) -> None:
    headers = {"X-Project-Key": KEY, "X-User-Id": user_id}
    res = requests.post(f"{BASE}/v1/events/track", json={"event_name": event_name, "properties": properties}, headers=headers, timeout=10)
    res.raise_for_status()


track("user-123", "purchase", {"amount": "99.99", "currency": "USD"})

Go

body, _ := json.Marshal(map[string]any{"event_name": "purchase", "properties": map[string]string{"amount": "99.99"}})
req, _ := http.NewRequest(http.MethodPost, "https://api.iforevents.com/v1/events/track", bytes.NewReader(body))
req.Header.Set("X-Project-Key", os.Getenv("IFOREVENTS_PROJECT_KEY"))
req.Header.Set("X-User-Id", userID) // your id for the person
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)

Batching

Buffer events on your side and flush every few seconds or every 500 events:

{
  "events": [
    { "name": "page_view", "type": "page_view", "properties": { "page": "/" } },
    { "name": "button_click", "properties": { "button": "signup" }, "created_at": "2026-09-11T12:00:00Z" }
  ]
}

One batch is one user (the X-User-Id of the request), so group buffered events by user before flushing. Batches are accepted with 202 and processed asynchronously; keep them under 500 items and a few hundred kilobytes.

Errors

StatusMeaningWhat to do
201 / 202AcceptedNothing
400Invalid body (missing event_name, custom_id or events)Fix the payload
401Unknown or rotated project keyUse the key from Settings → Project
413Body too largeSplit the batch
429Rate limited, or monthly quota exceeded after the grace period ({"error":"quota_exceeded"})Back off; upgrade the plan
5xxServer errorRetry with exponential backoff

Retry only when no 2xx came back (network errors, 5xx, 429): an accepted event gets its own id on the server, so re-sending an accepted batch counts it twice.

Client libraries (JavaScript, Python, Go)

Generated clients for the whole API, from ingest to analytics

Data Model

Events, users, properties and retention

On this page

EndpointscurlNode.jsPythonGoBatchingErrors