← Back to list

How to Actually Use the Adjust S2S API (Without Losing Your Mind)

If you work long enough in mobile attribution, you eventually run into a moment where the SDK just isn’t enough. Maybe you’re doing…

Emre Bayram · 2025-11-25 07:58 · 0 claps · 1.6 min read paywalled
#adjust #adjust-s2s #adjust-api
Open on Medium ↗
Wiki topics: GRW · Growth & Analytics

How to Actually Use the Adjust S2S API (Without Losing Your Mind)

If you work long enough in mobile attribution, you eventually run into a moment where the SDK just isn’t enough. Maybe you’re doing server-side revenue verification. Maybe you’re generating machine-learning predictions (like churn or LTV) and you want those predictions to flow back into your attribution layer. Or maybe you just want deterministic, reproducible event handling on your backend.

Whatever the reason, this is usually when people end up Googling “Adjust S2S API example,” landing on confusing docs, and wondering why their requests keep returning a mysterious 202 missing authentication token.

So here’s a clean, practical guide — from one engineer to another — on how to correctly implement Adjust’s server-to-server API and avoid the common traps.

Why Even Bother With S2S?

In most apps you’d rely on the Adjust SDK. It works fine. But there are real reasons to go S2S:

  • You want to send events AFTER some backend process (LTV prediction, internal fraud check, scoring, fulfillment, etc.).
  • You don’t fully trust the client side.
  • You want to unify events across multiple platforms where the SDK is hard to integrate.
  • You want consistent ordering and persistence (server logs don’t get erased when a user uninstalls the app).

Once you get S2S right, it feels more deterministic, more testable, and more transparent.

Adjust Doesn’t Accept device_id

There is no such parameter as "device_id" in the S2S API.

You must send the platform-specific device identifier, like:

  • iOS → idfa (or idfv if you have it)
  • Android → gps_adid
  • Amazon → amazon_adid
  • Console/web/other → external_device_id

If you send device_id=..., Adjust will basically shrug and pretend it didn’t see anything.

What You Need Before Making a Request

Make sure you have:

  • App Token (from Adjust dashboard)
  • Event Token (per event)
  • At least one correct device identifier
  • Optional but common: callback_params, partner_params, created_at_unix
  • Check if S2S Authentication Is Enabled

There’s a setting in Adjust → Protection → S2S Security.

If this is toggled ON (even just for Events), every S2S request must include your s2s token as Bearer.

So here is the code:

import json
import requests
from datetime import datetime, timezone
ADJUST_URL = "https://s2s.adjust.com/event"
def send_adjust_event(
 idfa: str,
 predicted_ltv: float,
 app_token: str,
 event_token: str,
 s2s_auth_token: str | None = None
):
params = {
 "s2s": "1",
 "app_token": app_token,
 "event_token": event_token,
 "idfa": idfa,
 "created_at_unix": str(int(datetime.now(timezone.utc).timestamp())),
 "callback_params": json.dumps({"predicted_ltv": predicted_ltv}),
 "partner_params": json.dumps({"predicted_ltv": predicted_ltv}),
 }
headers = {}
 if s2s_auth_token:
 headers["Authorization"] = f"Bearer {s2s_auth_token}"
resp = requests.post(ADJUST_URL, data=params, headers=headers)
 return resp

That is all.


메타데이터
post_id
c161e8a4a474
slug
how-to-actually-use-the-adjust-s2s-api-without-losing-your-mind-c161e8a4a474
url
https://medium.com/@bayramemre/how-to-actually-use-the-adjust-s2s-api-without-losing-your-mind-c161e8a4a474
canonical_url
https://medium.com/@bayramemre/how-to-actually-use-the-adjust-s2s-api-without-losing-your-mind-c161e8a4a474
author_url
https://medium.com/@bayramemre
status
ok
fetched_at
2026-07-14 22:58:46