Skip to the page
Docs
Send from your server

Docs Guides

Send events from your server

Some things happen on your server, not on the phone: a subscription renews, a webhook arrives, a job finishes. Send them to Apparent over HTTP with the same batch the SDKs use. Nothing to install.

The write key is safe on your server

The key (k) only lets you add events. It already ships inside your app, so it is not a secret, and keeping it in your server's settings is fine. Find it on the Connect page.

Send an event

import { randomUUID } from "node:crypto";

export async function track(userId, name, props = {}) {
  const now = Date.now();
  const res = await fetch("https://in.apparent.fyi/i", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      a: process.env.APPARENT_APP,
      k: process.env.APPARENT_KEY,
      v: "server-0.1.0",
      sa: now,
      d: { platform: "ios", os: "18.0", app: "1.0.6", locale: "en-US",
           anon: userId, user: userId },
      e: [{ n: name, t: now, s: "server",
            i: randomUUID().replaceAll("-", ""), p: props }],
    }),
  });
  if (!res.ok) throw new Error(`Apparent answered ${res.status}`);
}

A good answer is {"ok":true,"accepted":1,...}. 401 means the app id or key is wrong. On 408, 429 or 5xx, wait and send the same batch again (same i). On 401 or other 4xx, stop.

Who it was

  • A signed-in person: put your own account id in user (or u on one event). Apparent counts everyone with the same user id as one person, across all their phones and reinstalls, so this event joins the same person as their app events. Use the same id you pass to identify() in the app.
  • Send the user id as anon too. People are found through anon, so one shared value for every user (like "server") would merge them all into the first person. With anon equal to user the event lands on that person, and on the same person as their phone events.
  • An event with no user id counts as its own person, one per anon.
  • A server event is not someone opening the app, so it doesn't make a person "active" on its own. Their app visits do.

The event id

i is a random id for each event (32 hex characters, up to 80). Send the same one when you retry: the server keeps one copy per id, so sending twice is safe. For a webhook, a hash of the webhook's own id works well, so a repeated delivery never counts twice.

All fields and limits are in the Intake API.

Updated 2026-10-24 · Markdown · Report a mistake