Session Offers API specification (S2S)
This document outlines the endpoint necessary to retrieve Offer content from Rokt using the Session API (v2).
For the same contract as an interactive, schema-level reference, see the Session API reference.
Work with your Rokt account team to obtain the necessary credentials. For an end-to-end integration walkthrough, see Session API integration (S2S).
EndpointDirect link to Endpoint
| Environment | Action | URL |
|---|---|---|
| Production | POST | https://api.rokt.com/v2/sessions/offers |
There is no separate sandbox URL. To validate before going live, send the rokt-test-session: true header on the same endpoint. 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.
RequestDirect link to Request
Authorization headersDirect link to Authorization headers
| Header | Description | Type | Note |
|---|---|---|---|
Authorization | Basic auth credentials | string | Basic base64(rpub:rsec) — use the public and secret API keys provided by your account team. |
rokt-account-id | Your Rokt account ID | string | Required on every call. This is the source of account identity on the Session API. |
HeadersDirect link to Headers
| Header | Description | Type | Example |
|---|---|---|---|
Content-Type | Media type | string | application/json |
rokt-platform-type | Platform the offers are being requested for. Can be sent as channel.rokt_platform_type in the body instead (preferred); the header takes precedence when both are sent. | string | iOS, Android, Web, WebDesktop, or WebMobile (case-insensitive). Defaults to Web. |
rokt-package-name | App identifier of the native app the offers are being requested for. Required when rokt-platform-type is iOS or Android; ignored for web platforms. Can be sent as page.package_name in the body instead. | string | iOS bundle ID (com.example.app) or Android package name (com.example.android) |
rokt-ui-locale | User interface language and country. | string | ISO locale and country identifier, e.g. en-US |
rokt-client-unique-id | A unique reference for the transaction, for troubleshooting across partner and Rokt systems. Used as the confirmation reference when neither transaction.confirmation_ref nor a confirmation reference attribute is sent. | string | ORDER-000123 |
Additional headers for native app (iOS / Android) requestsDirect link to Additional headers for native app (iOS / Android) requests
When the offers are for a native app, send the device context as headers, exactly as on the v1 Server Offers API. Rokt cannot derive these from a server-to-server call.
| Header | Description | Type | Example |
|---|---|---|---|
rokt-os-type | OS type (case-insensitive). | string | iOS or Android |
rokt-os-version | OS version. | string | 17.4 or 14 |
rokt-device-model | Device model for iOS, or build model for Android. | string | iPhone15,2, Pixel 8 |
rokt-package-name | Package name or bundle identifier of the host app. See Headers. | string | com.example.app |
rokt-package-version | Package or bundle version of the host app. This is the app's version, not the Rokt SDK version. | string | 1.0.5 |
Also send the platform as channel.rokt_platform_type (or the rokt-platform-type header) so the request is treated as native app traffic.
Server-to-server traffic classifies as Web by default. If your Rokt pages are configured for a native platform (iOS or Android), send the platform as channel.rokt_platform_type in the body (or the rokt-platform-type header) — otherwise page detection will not match your native-configured pages and will return no offers. Web-configured pages need neither.
Native pages are matched on page_identifier and package name together. An iOS or Android request without a package name (header or page.package_name) matches no page and returns no offers. The value must match the package name configured on your Rokt page — confirm it with your account team.
Root/BodyDirect link to Root/Body
| Property | Required | Type | Description |
|---|---|---|---|
channel | Yes | object | See Channel. Must contain "type": "s2s". |
page | Yes | object | See Page. |
customer | No | object | See Customer. |
transaction | No | object | See Transaction. |
payment | No | object | See Payment. |
device | No | object | See Device. |
attributes | No | object | Free-form string → string map for any partner-specific signal that doesn't fit a typed object. |
Send only values you own. Rokt-derived attributes — geo, age and other demographics, device type/OS/version, payment method, and ML signals — are computed server-side and overwritten if sent; do not include them in attributes. For native app requests, pass device OS and model through the native app headers.
ChannelDirect link to Channel
| Property | Required | Type | Description |
|---|---|---|---|
type | Yes | string | Must be "s2s". |
rokt_platform_type | Native only | string | Platform the offers are being requested for: iOS, Android, Web, WebDesktop, or WebMobile (case-insensitive; anything else falls back to Web). Body equivalent of the rokt-platform-type header (the header takes precedence when both are sent). Required — here or as the header — when your Rokt pages are configured for a native platform. |
sdk_version | No | string | Version of the native app making the request. Enables native-mobile version attributes (version-based targeting, and scoping mitigations to affected app versions). Only applied when the platform identifies a native mobile platform. |
PageDirect link to Page
| Property | Required | Type | Description |
|---|---|---|---|
page_identifier | Yes | string | Text used to differentiate views/pages. |
package_name | Native only | string | App identifier (iOS bundle ID or Android package name). Required when rokt-platform-type is iOS or Android unless sent via the rokt-package-name header, which takes precedence. |
page_variation_code | No | string | Optional variation code for the page. |
CustomerDirect link to Customer
| Property | Required | Type | Description |
|---|---|---|---|
email | No | string | Customer email address. |
first_name | No | string | Customer first name. |
last_name | No | string | Customer last name. |
gender | No | string | Customer gender. |
postal_code | No | string | Customer postal/zip code. |
language | No | string | Customer language code (e.g. en). |
TransactionDirect link to Transaction
| Property | Required | Type | Description |
|---|---|---|---|
transaction_value | No | number | Value of the transaction. |
currency | No | string | ISO 4217 currency code (e.g. USD). |
confirmation_ref | No | string | Partner-side order or confirmation reference. |
PaymentDirect link to Payment
| Property | Required | Type | Description |
|---|---|---|---|
type | No | string | Payment method type (e.g. card). |
DeviceDirect link to Device
| Property | Required | Type | Description |
|---|---|---|---|
user_agent | No | string | User agent string of the client device or application. |
Request exampleDirect link to Request example
POST https://api.rokt.com/v2/sessions/offers
Authorization: Basic base64(rpub:rsec)
rokt-account-id: <your Rokt account ID>
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"
}
}
Request example (native app)Direct link to Request example (native app)
POST https://api.rokt.com/v2/sessions/offers
Authorization: Basic base64(rpub:rsec)
rokt-account-id: <your Rokt account ID>
Content-Type: application/json
rokt-ui-locale: en-US
rokt-client-unique-id: ORDER-000123
rokt-os-type: iOS
rokt-os-version: 17.4
rokt-device-model: iPhone15,2
rokt-package-version: 1.0.5
{
"channel": { "type": "s2s", "rokt_platform_type": "iOS" },
"page": { "page_identifier": "checkout", "package_name": "com.example.app" },
"customer": {
"email": "jane.doe@example.com",
"first_name": "Jane",
"last_name": "Doe",
"postal_code": "10001"
},
"transaction": {
"transaction_value": 19.99,
"currency": "USD",
"confirmation_ref": "ORDER-000123"
}
}
ResponseDirect link to Response
Success response (2xx)Direct link to Success response (2xx)
A 2xx response returns the offer directly — there is no success/errors envelope. plugins may be empty, which is a valid no-fill scenario representing a real share of production traffic: render nothing and continue the page.
Key fieldsDirect link to Key fields
| 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"] |
| Disclaimer | …offer.creative.copy["creative.disclaimer"] |
| Terms & Conditions link | …offer.creative.copy["creative.termsAndConditions.link"] |
| Privacy Policy link | …offer.creative.copy["creative.privacyPolicy.link"] |
| 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 (use as event page_instance_guid) | page_instance_guid |
Page token (use as event token on a dismissal) | page_context.token |
Session ID (use as event session_id) | session_id |
| Session token (refreshed session reference) | session_token.token |
| Experience ID | plugins[].plugin.config.experience_id |
| Configurables (dynamic rendering parameters) | plugins[].plugin.config.configurables |
| Targeting data (Digital Services Act disclosure) | plugins[].targeting_data |
Response optionDirect link to Response option
Each entry in …offer.creative.response_options_map (keyed positive / negative):
| Property | Type | Description |
|---|---|---|
action | string | CaptureOnly — record the response event only. Url — open url and record the response event. |
instance_guid | string | Unique to this response option. Use as the event parent_id when reporting the response. |
token | string | Event token for this response option. |
signal_type | string | The event type to send when the customer interacts. Almost always SignalResponse. |
short_label / long_label | string | Labels to display on the button or link. |
is_positive | boolean | Whether the response is a positive or negative engagement. |
url | string | URL to open when action is Url. |
url_behavior | string | How to open url (for example newTab). |
Targeting dataDirect link to Targeting data
Returned when Rokt provides a Digital Services Act disclosure for the offers; omitted otherwise.
| Property | Type | Description |
|---|---|---|
link | string | Link to details on why this selection of offers was shown, including the advertisers' information for the session. Displaying it supports Digital Services Act obligations. |
copy | string | Text explaining how partners use Rokt to determine the most relevant offers. |
advertisers | Advertiser[] | The advertisers behind the offers, in the order the offers are shown. |
AdvertiserDirect link to Advertiser
| Property | Type | Description |
|---|---|---|
name | string | The advertiser's legal entity name. |
brand | string | The advertiser's brand name. |
Example success response (2xx)Direct link to Example success response (2xx)
A layout-configured account returns populated outer_layout_schema and per-slot layout_variant fields; a data-integration account returns the same offer/creative content with those layout schemas empty. All values below are synthetic examples — read the fields you need using the Key fields paths above.
{
"session_id": "b1fb003c-e904-4083-b7b9-03cde555a7a1",
"page_instance_guid": "018f2a1b-0000-7abc-8def-page00000001",
"page_context": {
"page_instance_guid": "018f2a1b-0000-7abc-8def-page00000001",
"token": "<event-token>"
},
"session_token": {
"token": "<session_token>"
},
"plugins": [
{
"plugin": {
"id": "3353172846080032866",
"name": "dcui",
"config": {
"instance_guid": "ce5158a9-dc59-4a97-9006-a299901e4587",
"outer_layout_schema": "<JSON-encoded layout schema>",
"layout_schema_version": "2.0",
"slots": [
{
"instance_guid": "8f492d28-83fb-4813-877e-26e752ea9474",
"offer": {
"campaign_id": "2749386944931233793",
"account_id": "<your Rokt account ID>",
"creative": {
"referral_creative_id": "2760914349384466797",
"instance_guid": "c9f37d78-731d-4a0e-b8bc-712bd8c46cc1",
"advertiser": {
"name": "Example Advertiser Inc.",
"brand": "Example Brand"
},
"copy": {
"creative.title": "Get 20% off your next order",
"creative.image.src": "https://example.com/creative/hero.png",
"creative.disclaimer": "New customers only. Terms apply.",
"creative.termsAndConditions.link": "https://example.com/terms",
"creative.privacyPolicy.link": "https://example.com/privacy"
},
"response_options_map": {
"positive": {
"id": "2760914349384466794",
"action": "Url",
"instance_guid": "1d47ded1-b483-44e6-abf8-1d1d5faa82bc",
"signal_type": "SignalResponse",
"short_label": "Yes",
"long_label": "Yes please",
"is_positive": true,
"url": "https://example.com/redeem",
"url_behavior": "newTab",
"token": "<event-token>"
},
"negative": {
"id": "2760914349384466796",
"action": "CaptureOnly",
"instance_guid": "24de5c75-ff04-41c5-b3f7-7d2ee129ecc6",
"signal_type": "SignalResponse",
"short_label": "No thanks",
"long_label": "No thanks",
"is_positive": false,
"token": "<event-token>"
}
},
"token": "<event-token>"
}
},
"layout_variant": {
"layout_variant_id": "3353172846080032865",
"module_name": "standard-marketing",
"format_type": "Text",
"layout_variant_schema": "<JSON-encoded layout schema>"
},
"token": "<event-token>"
}
]
}
},
"fonts": []
}
]
}
No-fill response (2xx)Direct link to No-fill response (2xx)
When there are no relevant offers for a particular user, Rokt returns a 2xx with an empty plugins array. Render nothing and continue your page.
{
"plugins": [],
"page_instance_guid": "018f2a1b-0000-7abc-8def-page00000001",
"session_token": {
"token": "<session_token>"
}
}
Error responses (4xx / 5xx)Direct link to Error responses (4xx / 5xx)
Errors return a semantic HTTP status with a structured body:
{
"error": "<code>",
"message": "<detail>"
}
Validation failures carry error: "validation_failed" and an additional details[] array naming each offending field.
Common error codesDirect link to Common error codes
| HTTP status | Meaning |
|---|---|
400 | Malformed request body, or a body that failed validation (error: "validation_failed"). |
401 | Missing or invalid Authorization header. |
429 | Rate limited. Do not retry automatically — pause and contact your Rokt representative if 429s persist. |
5xx | Unexpected server error. Retry after a brief delay (1–2 seconds). If the problem persists, contact support@rokt.com. |
Caching offersDirect link to Caching offers
To maximize revenue opportunities, fetch offer content from /v2/sessions/offers earlier in the user's transaction journey — before the offer is expected to render — then cache it for fast client retrieval within the same transaction.
We recommend caching against a combination of unique transaction ID, user ID, and user device type. If the user context shifts (e.g. device change), re-fetch with updated attributes to ensure offer relevance.
Migrating from the v1 Server Offers APIDirect link to Migrating from the v1 Server Offers API
If you integrated with the v1 Server Offers API (POST /v1/partner/offers), use these mappings.
HeadersDirect link to Headers
| v1 header | Session API (v2) equivalent |
|---|---|
rokt-pub-id, rokt-secret | Authorization: Basic base64(rpub:rsec) |
rokt-tag-id | rokt-account-id |
content-type, accept | Unchanged |
rokt-ui-locale | Unchanged |
rokt-client-unique-id | Unchanged. Prefer transaction.confirmation_ref for the order reference. |
rokt-platform-type | Unchanged, or channel.rokt_platform_type in the body. Send iOS or Android instead of Mobile. |
rokt-os-type, rokt-os-version, rokt-device-model | Unchanged |
rokt-package-name | Unchanged, or page.package_name in the body |
rokt-package-version | Unchanged |
Request bodyDirect link to Request body
| v1 field | Session API (v2) equivalent |
|---|---|
pageIdentifier | page.page_identifier |
attributes | Typed objects (customer, transaction, payment, device) where one fits; attributes for anything else |
attributes.userAgent | device.user_agent |
ResponseDirect link to Response
| v1 field | Session API (v2) equivalent |
|---|---|
sessionId | session_id |
pageInstanceGuid | page_instance_guid |
success | The HTTP status code — there is no envelope |
placements[] | plugins[] |
placements[].placementGuid | plugins[].plugin.config.instance_guid |
placements[].experienceId | plugins[].plugin.config.experience_id |
placements[].configurables | plugins[].plugin.config.configurables |
placements[].targetingData | plugins[].targeting_data |
placements[].offers[] | plugins[].plugin.config.slots[].offer |
offers[].slotGuid | slots[].instance_guid |
offers[].creativeGuid | …offer.creative.instance_guid |
offers[].creativeId | …offer.creative.referral_creative_id |
offers[].campaignId | …offer.campaign_id |
offers[].copy | …offer.creative.copy |
offers[].advertiser | …offer.creative.advertiser |
offers[].formatType | slots[].layout_variant.format_type |
offers[].responseOptions[] | …offer.creative.response_options_map (positive / negative) |
responseOptions[].responseOptionGuid | response_options_map[key].instance_guid |
In v2, each element you report on (slot, creative, response option) also carries a token. Send it with the element's instance_guid on the events call.