Session API integration (S2S)
Integrate with Rokt server-to-server using the unified Session API (v2) — the same
/v2/sessions/* endpoints that power Rokt's SDKs. Your server calls Rokt to
retrieve an offer, renders it, and reports engagement and conversion events back.
Work with your Rokt account team to obtain credentials.
EndpointsDirect link to Endpoints
| Purpose | Method | URL |
|---|---|---|
| Get offers | POST | https://api.rokt.com/v2/sessions/offers |
| Report events | POST | https://api.rokt.com/v2/sessions/events |
For the full request/response reference for each endpoint, see the Offers API specification and the Events API specification.
Server-to-server traffic classifies as Web by default. If your Rokt pages are configured for a native platform (iOS or Android), set the rokt-platform-type header to that platform on every offers call — otherwise the request is treated as Web, your native-configured pages will not match, and page detection returns no offers. Web-configured pages need no header. Accepted values are iOS, Android, Web, WebDesktop, and WebMobile (case-insensitive); anything else falls back to Web.
To validate before going live, send the rokt-test-session: true header on the same endpoints — there is no separate sandbox URL. Test sessions are tagged and filtered out of production metrics; the header marks reporting only — it does not force an offer to serve. For deterministic end-to-end testing, your account team can configure a staging page with dedicated test campaigns. Remove the header to go live.
AuthenticationDirect link to Authentication
- The
rokt-account-idheader is required on every call (offers and events) — it is the source of account identity on the Session API. - Offers call — on your first, session-less call, authenticate with
Authorization: Basic base64(rpub:rsec), whererpubandrsecare the public and secret API keys provided by your account team. (Authorization: Bearer <session_token>is used only to continue an existing session.) - Events call — authenticate with
Authorization: Basic base64(rpub:rsec), using the same public and secret API keys as the offers call.
1. Request offersDirect link to 1. Request offers
Send a typed request body and set channel.type to "s2s". All values below are synthetic examples.
POST https://api.rokt.com/v2/sessions/offers
Authorization: Basic base64(rpub:rsec)
rokt-account-id: <your Rokt account ID>
rokt-platform-type: <iOS | Android | Web>
Content-Type: application/json
{
"channel": { "type": "s2s" },
"page": { "page_identifier": "checkout" },
"customer": {
"email": "jane.doe@example.com",
"first_name": "Jane",
"last_name": "Doe",
"gender": "F",
"postal_code": "10001",
"language": "en"
},
"transaction": {
"transaction_value": 19.99,
"currency": "USD",
"confirmation_ref": "ORDER-000123"
},
"payment": { "type": "card" },
"device": {
"user_agent": "YourApp/1.0 (mobile)"
},
"attributes": {
"your_custom_attribute": "value"
}
}
- Top-level objects (
page,customer,transaction,payment,device,cart,shipping) are typed and accept only their defined fields; put any partner-specific signal that doesn't fit them into the free-formattributesstring map. - Send only values you own. Rokt-derived attributes — geo, age and other demographics (from the Rokt profile), device type/OS/version (parsed from the user agent), payment method/sub-method (from the card BIN), and ML/Carbon signals — are computed server-side and overwritten if sent; don't include them.
2. Parse the offers responseDirect link to 2. Parse the offers response
A 2xx returns the offer directly (there is no success/errors envelope). plugins may be empty — a valid no-fill and a real share of production traffic: render nothing and continue your page. slots contains only the slots that actually filled, up to the maximum your layout defines. Read the offer from the nested plugin structure; on any non-2xx, parse the structured error body.
| What you need | Path in the response |
|---|---|
| Offer | plugins[].plugin.config.slots[].offer |
| Title / copy | …offer.creative.copy["creative.title"] |
| Image | …offer.creative.copy["creative.image.src"] |
| Advertiser | …offer.creative.advertiser |
| Positive action + URL | …offer.creative.response_options_map.positive.url |
| Decline action | …offer.creative.response_options_map.negative |
Element instance IDs (use as event parent_id) | …slots[].instance_guid, …offer.creative.instance_guid, …response_options_map[key].instance_guid |
Page instance (event page_instance_guid) | page_instance_guid |
Session ID (event session_id) | session_id |
| Session token (refreshed session reference) | session_token.token |
Errors return a semantic HTTP status with a body of { "error": "<code>", "message": "<detail>" } (validation failures add a details[] array).
3. Render the offerDirect link to 3. Render the offer
How you render depends on how your account's layouts are configured — confirm with your Rokt team which contract your account serves:
- Self-render (data integration) — the response carries the offer's components (creative copy, image, response options — the paths in step 2) with no layout description: you draw the offer in your own UI to match your page, and report each engagement event yourself (step 4).
- Rokt UX Helper (Rokt-designed layouts) — the response's
plugins[]carry a full layout description that Rokt's open-source UX Helper libraries (Web, iOS, Android) render inside your UI, raising the engagement events for you to forward. Note the UX Helpers consume the Experiences API payload shape; the Session API returns the same layout content in a different envelope (snake_case), so pairing them with/v2/sessions/offerscurrently requires a small response adaptation — ask your Rokt team.
You can tell the contracts apart from the response itself: a data-integration account returns offers with empty layout schemas, while a layout account returns populated outer_layout_schema and per-slot layout_variant fields.
4. Report eventsDirect link to 4. Report events
Report engagement and conversion events to /v2/sessions/events, authenticated with the same Basic credentials as the offers call. Identify the session with single_session: true and the top-level session_id returned by the offers response on each event.
POST https://api.rokt.com/v2/sessions/events
Authorization: Basic base64(rpub:rsec)
rokt-account-id: <your Rokt account ID>
Content-Type: application/json
{
"channel": { "type": "s2s" },
"single_session": true,
"events": [
{
"event_type": "impression",
"instance_id": "018f1234-5678-7abc-8def-0123456789ab",
"session_id": "018f2a1b-2222-7abc-8def-session00001",
"timestamp": 1751234567000,
"data": {
"parent_id": "018f2a1b-3333-7abc-8def-creative001",
"page_instance_guid": "018f2a1b-0000-7abc-8def-page00000001",
"token": "<event-token>",
"capture_method": "ClientProvided"
}
}
]
}
-
event_type— the event kind as a snake_case string. Common values:Event event_typeImpression impressionViewed viewedPositive / negative response signal_responseDismissal dismissalConversion conversion_signalPurchase purchase -
instance_id— a client-generated UUID identifying this event, used to deduplicate. -
session_id— the top-levelsession_idreturned by the offers response. -
data.parent_id— theinstance_guidof the element the event is about, taken from the offers response (e.g. the creative'sinstance_guidfor an impression, a response option's for a response). Builds the session tree. Echo the value verbatim; it may carry a type prefix such asad:<uuid>. -
data.page_instance_guid— thepage_instance_guidfrom the offers response. -
data.token— the event token for that element from the offers response. -
timestamp— Unix epoch milliseconds. -
Set
single_sessiontotrueand includesession_idon every event in the request.
A successful call returns 202 Accepted with session_token (refreshed for the next call), event_ids[], errors[] (per-event {index, code, message}), and warnings[].
ChecklistDirect link to Checklist
- Confirm credentials and the full API reference with your Rokt account team.
- Call
/v2/sessions/offerswith the typed body,channel.type: "s2s", and therokt-account-idheader (plusrokt-platform-typeif your pages are configured for a native platform). - Parse the offer from
plugins[].plugin.config.slots[].offer.creative; use the HTTP status for success/failure, and handle emptyplugins(no-fill) by rendering nothing. - Render the offer yourself or via a UX Helper library, per your account's layout configuration.
- Capture
session_idand report events to/v2/sessions/eventsusing Basic authentication,single_session: true, a per-eventsession_id, and the response'sdata.parent_idanddata.page_instance_guidvalues. - Validate with the
rokt-test-session: trueheader (reporting-only — it does not force an offer to serve), then remove it to cut over to production.