Server API

Send users and events to Atlis from your backend, CRM or automation tool.

Available on: Growth, Scale or an active trial

Use the server API when data lives on your server, in a CRM, or in a tool like Zapier. It works on its own or alongside the tracking snippet.

1. Get your API key

Go to Settings → Integrations → Server API & CRM and click Generate API key. The key starts with atlis_sk_ and is shown only once, so store it somewhere safe. Regenerate key replaces it, and the old key stops working immediately.

Keep the key on your server or in your CRM. Never put it in browser code.

2. Create or update a user

POST /api/v1/identify creates the user if they're new, or updates them. Send it before any events for that user.

cURL
curl -X POST https://theatlis.com/api/v1/identify \
  -H "Authorization: Bearer atlis_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "12345",
    "email": "jane@company.com",
    "name": "Jane Smith",
    "plan": "pro",
    "isActivated": false,
    "trialExpiresAt": "2026-12-01T00:00:00Z",
    "signedUpAt": "2026-09-01T10:00:00Z",
    "properties": { "company": "Acme" }
  }'
FieldTypeNotes
userIdstring, requiredYour permanent ID for this person. Must not contain /.
emailstringNeeded to send them emails.
namestringUsed as {{displayName}} in emails.
planstringFor example free, trial, pro, annual.
isActivatedtrue / falseWhether they reached your activation milestone.
trialExpiresAtISO date or millisecondsTrial end date. Powers Trial expiring in 3 days.
signedUpAtISO date or millisecondsReal signup date, used only when the user is first created. Future dates and dd/mm/yyyy formats are ignored.
lastActiveAtISO date or millisecondsWhen they were last active in your product. Only moves forward, never back.
sourceTagstringWhere the user came from, for example Website or Google Ads.
firstTouch / lastTouchobjectOptional traffic details for the first and latest visit: source, medium, campaign, content, term, referrer, landing_page. The first touch is kept once set, and it takes priority over sourceTag.
propertiesobjectAny extra fields. Empty values are ignored, so they never erase existing data.
eventNamestringOptional: also record an event in the same call (see below).
messageIdstringOptional: a unique ID for that event, so a retry doesn't send twice.

A successful call returns 200 {"success": true}.

3. Send an event

POST /api/v1/events records something the user did. If a workflow for that trigger is switched on, its email sends.

cURL
curl -X POST https://theatlis.com/api/v1/events \
  -H "Authorization: Bearer atlis_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "12345",
    "eventName": "trial_started",
    "messageId": "trial_started_12345",
    "properties": { "plan": "pro" }
  }'
FieldTypeNotes
userIdstring, requiredMust already exist. Identify the user first.
eventNamestring, requiredA trigger name such as trial_started, or your own custom name.
propertiesobjectOptional details saved with the event.
messageIdstringOptional unique ID. Sending the same messageId again is ignored, so retries are safe.

A successful call returns 200 {"ok": true}. The event time is the moment Atlis receives it. Events sent to this endpoint also count as activity, so they update the user's last active time.

Authentication

EndpointAccepted ways to send the key
/api/v1/identifyAuthorization: Bearer <key> header (recommended), an x-api-key header, or an apiKey field in the JSON body
/api/v1/eventsSame as identify: Authorization: Bearer <key> header, an x-api-key header, or an apiKey field in the JSON body
/api/v1/inboundSame as identify, plus ?key=<key> in the URL or the key as the Basic auth password

Code examples

JavaScript
// Node.js 18+ (uses the built-in fetch)
const ATLIS_KEY = process.env.ATLIS_API_KEY;

async function atlis(path, body) {
  const res = await fetch("https://theatlis.com/api/v1/" + path, {
    method: "POST",
    headers: {
      "Authorization": "Bearer " + ATLIS_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error("Atlis " + res.status + ": " + (await res.text()));
  return res.json();
}

await atlis("identify", { userId: "12345", email: "jane@company.com", name: "Jane Smith" });
await atlis("events", { userId: "12345", eventName: "first_project_created" });

Responses and errors

StatusErrorWhat to do
400Invalid JSON (identify)Send a valid JSON body with Content-Type: application/json.
400Missing required field: userId / missing_user_idAdd a userId.
400Invalid userId / invalid_user_idRemove any / from the ID.
400missing_event_nameAdd an eventName (events endpoint).
400Invalid messageId / invalid_message_idUse a plain text messageId without /.
400invalid_json (events)Send a valid JSON body with Content-Type: application/json.
400inbound_mapping_not_set / missing_user_id (inbound)Save the field mapping in Settings → Integrations → Server API & CRM, and check the mapped User ID or Email field isn't empty in the payload.
401invalid_api_key or UnauthorizedCheck the key is current and sent in one of the supported ways.
403plan_limit_exceededYour plan doesn't include the API, or you've reached your tracked-user limit.
403plan_upgrade_requiredThe events endpoint needs Growth, Scale or an active trial.
404unknown_userCall /api/v1/identify for this user first.
429rate_limitedSlow down. The events endpoint accepts up to 100 requests per minute per workspace.
500internal_server_error / Internal server errorRetry later.

Time-based emails for API users

  • The Inactive 7/14 days, Testimonial request and Not activated in 48h workflows depend on activity. Atlis skips them for API users until it has real activity for them.
  • Activity comes from /api/v1/events calls, a lastActiveAt value in identify, or the tracking snippet. Events sent inside an identify call (eventName) don't count as activity.
  • For CRM leads with no product activity, you can still send the Not activated email: see CRM status mapping.
  • Trial expiring in 3 days works for API users as long as you send trialExpiresAt.

Try it in your own workspace

Start with a 14-day trial with Growth features. No credit card needed.

Start free