Skip to content

RevoSurge Server Events API (v3)

Audience: Engineers, technical integrators, Admin teams

The Server Events API lets partners securely send user events directly from their servers to the DataPulse platform. v3 introduces a typed event catalog — events and fields are pre-registered and validated on ingest — and a structured request envelope.

Base URL

The base URL is unchanged from v2.

EnvironmentBase URL
Productionhttps://datapulse-api.revosurge.com/

Authentication

Every request must include your API key in the X-API-KEY header.

HeaderRequiredValue
X-API-KEYYesYour API key
Content-TypeYesapplication/json
X-Test-ModeNotrue to validate & echo without storing (see Test mode)

See API Key for how to obtain a key. Authentication is unchanged from v2.

The request envelope

A v3 event is a JSON object with four parts — event, timestamp, identity, and context:

json
{
  "event": "deposit",
  "timestamp": 1718280000000,
  "identity": {
    "client_user_id": "user_001",
    "click_id": "RS_clk_998877"
  },
  "context": {
    "ip_address": "203.0.113.1",
    "transaction_id": "txn_554433",
    "amount": 100.0,
    "currency": "USD",
    "is_crypto": false,
    "payment_method": "pix"
  }
}

Full field rules are on Request envelope & base properties. In short:

  • event (String, required) — a registered event name. Unknown names are rejected.
  • timestamp (Number, required) — UTC epoch milliseconds (13 digits).
  • identity (Object, required) — must include at least one of client_user_id or anonymous_id. click_id alone is not enough.
  • context (Object) — event-specific fields. PII goes under context.privacy.* and must be SHA-256 hashed.

Ingestion endpoints

Single event

POST/v3/s2s/event

The body is a single envelope object.

bash
curl -X POST "https://datapulse-api.revosurge.com/v3/s2s/event" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: dp_test_key_123" \
  -d '{
    "event": "deposit",
    "timestamp": 1718280000000,
    "identity": { "client_user_id": "user_001", "click_id": "RS_clk_998877" },
    "context": {
      "ip_address": "203.0.113.1",
      "transaction_id": "txn_554433",
      "amount": 100.0,
      "currency": "USD"
    }
  }'
js
const res = await fetch("https://datapulse-api.revosurge.com/v3/s2s/event", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-KEY": process.env.REVOSURGE_API_KEY,
  },
  body: JSON.stringify({
    event: "deposit",
    timestamp: Date.now(),
    identity: { client_user_id: "user_001", click_id: "RS_clk_998877" },
    context: {
      ip_address: "203.0.113.1",
      transaction_id: "txn_554433",
      amount: 100.0,
      currency: "USD",
    },
  }),
});
python
import os, time, requests

requests.post(
    "https://datapulse-api.revosurge.com/v3/s2s/event",
    headers={"X-API-KEY": os.environ["REVOSURGE_API_KEY"]},
    json={
        "event": "deposit",
        "timestamp": int(time.time() * 1000),
        "identity": {"client_user_id": "user_001", "click_id": "RS_clk_998877"},
        "context": {
            "ip_address": "203.0.113.1",
            "transaction_id": "txn_554433",
            "amount": 100.0,
            "currency": "USD",
        },
    },
)

Batch

POST/v3/s2s/batch

The body is a bare JSON array of envelopes (not an object with an events key). Maximum 600 events per request.

json
[
  { "event": "login",   "timestamp": 1718280000000, "identity": { "client_user_id": "user_001" }, "context": { "ip_address": "203.0.113.1" } },
  { "event": "deposit", "timestamp": 1718280001000, "identity": { "client_user_id": "user_001" }, "context": { "ip_address": "203.0.113.1", "transaction_id": "txn_1", "amount": 100.0, "currency": "USD" } }
]

NOTE

Exceeding 600 events returns 400 BATCH_TOO_LARGE.

Responses

On success, events are queued asynchronously (HTTP 202).

EndpointStatusBody
Single202 Accepted{ "status": "accepted", "eventId": "..." }
Batch202 Accepted{ "status": "accepted", "requestId": "...", "count": 150 }

Errors

Errors on /v3/s2s/* return a structured body with a code and a violations[] array:

json
{
  "code": "VALIDATION_ERROR",
  "message": "Envelope validation failed",
  "violations": [
    { "field": "timestamp", "rule": "not_milliseconds", "event": "deposit" },
    { "field": "context.amount", "rule": "type", "event": "deposit" }
  ]
}
StatusCodeMeaning
400VALIDATION_ERRORMissing/invalid fields, bad timestamp, malformed PII, type mismatch
400BATCH_TOO_LARGEMore than 600 events in a batch
422UNKNOWN_EVENT_TYPEevent is not a registered catalog event
422EVENT_DISABLEDThe event exists but is disabled for your product
429Rate limit exceeded ({ "error": "Too Many Requests" })

See Event catalog & validation for how the catalog drives these checks.

Test mode

Send X-Test-Mode: true to validate and enrich an event without publishing it. The response (HTTP 200) echoes the fully enriched event (geo, parsed user-agent, normalized amounts) so you can inspect exactly what DataPulse would store. For batch, the response includes per-item successCount / failureCount and an errors[] list with the failing index and reason.

Rate limits

  • Limits are applied per API key, on a rolling 1-minute window.
  • Exceeding the limit returns 429.
  • Use exponential backoff on 429 and 5xx.