SESSION Endpoint API Reference
Track user sessions and enable attribution for app installs, re-engagement, and retention metrics through Singular's REST API using server-to-server integration as an alternative to SDK implementation.
Overview
Server-to-Server Use Case
The SESSION endpoint notifies Singular when a user opens your app, powering install and re-engagement attribution and retention metrics. New to Server-to-Server? See the S2S Fundamentals guide for core concepts and shared setup.
Supported Capabilities:
- Install Attribution: First-touch attribution to marketing campaigns
- Re-engagement Attribution: Multi-touch attribution for returning users
- Retention Metrics: Session-based engagement tracking
Session Management
SESSION endpoint notifies Singular of app open events to initialize user sessions for attribution and tracking.
When to Send Sessions
Session Triggers
Send SESSION requests for these app lifecycle events:
- Fresh Installations: First app launch after install
- Terminated State Launch: App opens from fully closed state
- Background to Foreground: App returns to foreground after timeout period (recommended: 60 seconds)
Session Timeout Logic
Implement session timeout to prevent excessive SESSION requests during brief app backgrounding.
Recommended Implementation:
- Timeout Duration: 60 seconds (1 minute)
- Foreground < Timeout: Do not send SESSION if app returns to foreground within timeout period
- Foreground > Timeout: Send SESSION if app remains backgrounded beyond timeout period
- App Lifecycle Tracking: Use app lifecycle events and timers to manage session state
Deep Link Support:
Always send SESSION for app opens
via deep links, Universal Links, or App Links with the
openuri
parameter populated, regardless of timeout status.
Attribution Processing
Session-Based Attribution
Singular processes SESSION requests to determine attribution type and trigger appropriate workflows.
| Session Type | Singular Processing | Attribution Result |
|---|---|---|
| First Session (New Install) | Install attribution process triggered | Attributes install to marketing campaign |
| Re-engagement Qualified | Re-engagement attribution process triggered | Attributes user return to campaign or deep link |
| Standard Session | Session recorded for retention tracking | Counts toward user activity and engagement metrics |
Learn more: Re-engagement Attribution FAQ
Event Order Requirements
Session and event timing directly impacts attribution accuracy and data quality.
Critical Ordering Rules:
- Session Before Events: Single SESSION must be received before any events for that session
- Real-time Event Transmission: In-app events must be sent in real-time after their respective session
- Sequential Processing: Invalid session order results in data inconsistencies and attribution errors
API Endpoint Specification
SESSION endpoint accepts POST requests with parameters sent as
application/x-www-form-urlencoded
.
Endpoint
Base URL and Method
POST https://s2s.singular.net/api/v1/launch
Required header:
Content-Type: application/x-www-form-urlencoded
Request Format:
POST /api/v1/launch HTTP/1.1
Host: s2s.singular.net
Content-Type: application/x-www-form-urlencoded
param1=value1¶m2=value2
Required Parameters
All SESSION requests must include these required parameters with proper values and formatting.
API Authentication
SDK Key
| Parameter | Details |
|---|---|
a
|
Type:
String
Important: Do not use the Reporting API Key. Requests will be rejected.
Example:
|
Device Identifiers
Platform-Specific Identifiers
| Parameter | Details |
|---|---|
idfa
|
Platform:
iOS
|
idfv
|
Platform:
iOS
|
aifa
|
Platform:
Android
|
asid
|
Platform:
Android
|
amid
|
Platform:
Android
|
oaid
|
Platform:
Android
|
andi
|
Platform:
Android
Restricted use: Prohibited on Google Play devices—use AIFA and ASID instead. Only send if no other identifiers are available and the app is not distributed via Google Play.
Example:
|
sdid
|
Platform:
iOS, Android, PC, Xbox, PlayStation, Nintendo, MetaQuest, CTV
|
Device Parameters
Device Information
| Parameter | Details |
|---|---|
p
|
Type:
String
|
ip
|
Type:
String
|
ve
|
Type:
String
|
ma
|
Platform:
iOS, Android
|
mo
|
Platform:
iOS, Android
|
lc
|
Platform:
iOS, Android
|
bd
|
Platform:
iOS, Android
|
Application Parameters
App Information
| Parameter | Details |
|---|---|
i
|
Type:
String
|
app_v
|
Type:
String
|
att_authorization_status
|
Platform:
iOS
Always required:
Even if ATT is not implemented, pass
Example:
|
| Parameter | Details |
|---|---|
install
|
Type:
Boolean
|
install_time
|
Platform:
iOS, Android
This is the device install time, not Singular's attribution install
time. Attribution uses the session timestamp (
See the Device Data Retrieval Guide for how to obtain this value on iOS and Android. |
update_time
|
Platform:
iOS, Android
See the Device Data Retrieval Guide for how to obtain this value on iOS and Android. |
Fraud Prevention Parameters
Install Source Validation
| Parameter | Details |
|---|---|
install_source
|
Platform:
Android, PC
|
install_receipt
|
Platform:
iOS
|
Deep Linking Parameters
Deep Link Support
| Parameter | Details |
|---|---|
openuri
|
Platform:
iOS, Android
|
ddl_enabled
|
Platform:
iOS, Android
|
singular_link_resolve_required
|
Platform:
iOS, Android
|
Advanced Attribution Parameters
Platform Attribution Enhancement
| Parameter | Details |
|---|---|
install_ref
Native PC (Google Play Games)
|
Platform:
Android (Google Play)
|
meta_ref
|
Platform:
Android (Google Play)
As of June 18, 2025: Meta Advanced Mobile Measurement (AMM) removes need for Meta Install Referrer implementation. Not recommended if AMM enabled.
JSON URL-encoded Meta Install Referrer for granular user-level
attribution data.
|
attribution_token
|
Platform:
iOS
|
Optional Parameters
Optional parameters enhance tracking capabilities and support advanced features.
Timestamp Parameters
| Parameter | Details |
|---|---|
utime
|
Type:
Integer
|
umilisec
|
Type:
Integer
|
Network & Location Parameters
| Parameter | Details |
|---|---|
use_ip
|
Type:
Boolean
Limitations:
Example:
|
country
|
Type:
String
|
ua
|
Type:
String
|
c
|
Platform:
iOS, Android
|
cn
|
Platform:
iOS, Android
|
Custom Properties
| Parameter | Details |
|---|---|
global_properties
|
Type:
JSON
|
Uninstall Tracking Support
| Parameter | Details |
|---|---|
apns_token
|
Platform:
iOS
|
fcm
|
Platform:
Android
|
Data Privacy Parameters
| Parameter | Details |
|---|---|
data_sharing_options
|
Type:
JSON
|
dnt
|
Platform:
iOS, Android
|
dntoff
|
Platform:
iOS, Android
|
Cross-Device Support
| Parameter | Details |
|---|---|
custom_user_id
|
Type:
String
No PII: Do not pass personally identifiable information. Use a hashed or otherwise anonymized internal identifier, not raw email addresses, phone numbers, or names.
Example:
|
SKAdNetwork Support
| Parameter | Details |
|---|---|
skan_conversion_value
|
Platform:
iOS
|
skan_first_call_timestamp
|
Platform:
iOS
|
skan_last_call_timestamp
|
Platform:
iOS
|
Google Ads ICM Support (Beta)
| Parameter | Details |
|---|---|
odm_info
|
Platform:
iOS
|
odm_error
|
Platform:
iOS
|
Request Examples
Sample code demonstrates SESSION endpoint integration across multiple programming languages.
Example Disclaimer:
Code samples may not include
all required parameters. Validate complete parameter list before
production implementation. Use unique
i
(app identifier)
for development/testing.
Python Example
import requests
url = 'https://s2s.singular.net/api/v1/launch'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
data = {
'a': 'sdk_key_here',
'p': 'Android',
'i': 'com.singular.app',
'ip': '10.1.2.3',
've': '9.2',
'ma': 'samsung',
'mo': 'SM-G935F',
'lc': 'en_US',
'aifa': '8ecd7512-2864-440c-93f3-a3cabe62525b',
'asid': 'edee92a2-7b2f-45f4-a509-840f170fc6d9',
'install': 'true',
'n': 'MyCoolAppName',
'bd': 'Build/13D15',
'app_v': '1.2.3',
'openuri': 'myapp://home/page?queryparam1=value1',
'ddl_enabled': 'true',
'install_source': 'com.android.vending',
'install_time': 1510040127,
'update_time': 1510090877
}
response = requests.post(url, data=data, headers=headers)
print(response.json())
cURL Example
curl -X POST "https://s2s.singular.net/api/v1/launch" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "a=sdk_key_here" \
--data-urlencode "p=Android" \
--data-urlencode "i=com.singular.app" \
--data-urlencode "ip=10.1.2.3" \
--data-urlencode "ve=9.2" \
--data-urlencode "ma=samsung" \
--data-urlencode "mo=SM-G935F" \
--data-urlencode "lc=en_US" \
--data-urlencode "aifa=8ecd7512-2864-440c-93f3-a3cabe62525b" \
--data-urlencode "asid=edee92a2-7b2f-45f4-a509-840f170fc6d9" \
--data-urlencode "install=true" \
--data-urlencode "n=MyCoolAppName" \
--data-urlencode "bd=Build/13D15" \
--data-urlencode "app_v=1.2.3" \
--data-urlencode "openuri=myapp://home/page?queryparam1=value1" \
--data-urlencode "ddl_enabled=true" \
--data-urlencode "install_source=com.android.vending" \
--data-urlencode "install_time=1510040127" \
--data-urlencode "update_time=1510090877"
HTTP Example
POST /api/v1/launch HTTP/1.1
Host: s2s.singular.net
Content-Type: application/x-www-form-urlencoded
Accept: application/json
a=sdk_key_here&p=Android&i=com.singular.app&ip=10.1.2.3&ve=9.2&ma=samsung&mo=SM-G935F&lc=en_US&aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&asid=edee92a2-7b2f-45f4-a509-840f170fc6d9&install=true&n=MyCoolAppName&bd=Build%2F13D15&app_v=1.2.3&openuri=myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1&ddl_enabled=true&install_source=com.android.vending&install_time=1510040127&update_time=1510090877
Java Example
// Endpoint
String endpoint = "https://s2s.singular.net/api/v1/launch";
// Parameters
Map<String, String> params = new HashMap<>();
params.put("a", "sdk_key_here");
params.put("p", "Android");
params.put("i", "com.singular.app");
params.put("ip", "10.1.2.3");
params.put("ve", "9.2");
params.put("ma", "samsung");
params.put("mo", "SM-G935F");
params.put("lc", "en_US");
params.put("aifa", "8ecd7512-2864-440c-93f3-a3cabe62525b");
params.put("asid", "edee92a2-7b2f-45f4-a509-840f170fc6d9");
params.put("install", "true");
params.put("n", "MyCoolAppName");
params.put("bd", "Build/13D15");
params.put("app_v", "1.2.3");
params.put("openuri", "myapp://home/page?queryparam1=value1");
params.put("ddl_enabled", "true");
params.put("install_source", "com.android.vending");
params.put("install_time", "1510040127");
params.put("update_time", "1510090877");
// Build form-urlencoded body
StringBuilder form = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (form.length() > 0) form.append('&');
form.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8))
.append('=')
.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
byte[] body = form.toString().getBytes(StandardCharsets.UTF_8);
// Create connection
URL url = new URL(endpoint);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept", "application/json");
// Write body
try (OutputStream os = conn.getOutputStream()) {
os.write(body);
}
// Get response
int responseCode = conn.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println("HTTP Status Code: " + responseCode);
System.out.println("Response: " + response.toString());
conn.disconnect();
Response Format
Every SESSION request returns a JSON body. Which fields are present depends on whether Singular ran the deferred deep link flow for that session.
Standard Response
Returned for any session that does not trigger the deferred deep link flow — a session that is not the device's first, or a first session that requested neither deferred deep linking nor Attribution Info.
{
"status": "ok"
}
Deferred Deep Link Response
Returned when the session is the device's first and either ddl_enabled=true was sent or Attribution Info is enabled for your account. All fields below are present in this response, including empty ones.
{
"status": "ok",
"deferred_deeplink": "myapp://product/123",
"deferred_deeplink_source": "Redis",
"deferred_passthrough": "promo_code_xyz",
"attribution_info": null
}
| Field | Type | Notes |
|---|---|---|
status |
String | ok on success. Present in every response. |
deferred_deeplink |
String | The deferred deep link. An empty string when none was found. |
deferred_deeplink_source |
String | Where the touchpoint came from. One of Redis, Google, Facebook, Twitter, Snapchat, Tiktok Ads, Install Referrers, Google AdWords(Claim) or Apple Search Ads, or empty when no touchpoint was found. |
deferred_passthrough |
String | Passthrough values attached to the link. An empty string when none were set. |
attribution_info |
Object or null | Attribution result for the install. See the section below. |
resolved_singular_link |
String | The resolved Singular Link. Omitted entirely when no link was resolved. |
attribution_info Object
BETA feature: Attribution Info is not generally available and must be enabled for your account by Singular. Contact your Customer Success Manager to request it.
The field is always present in a Deferred Deep Link Response, and has three possible states:
- null — Attribution Info is not enabled for your account, or this is not a first session.
- An object whose network is Organic — enabled, but no touchpoint was found. This is a result, not an error.
- A populated object — enabled, and a touchpoint was matched. Only fields with a value are included.
{
"attribution_info": {
"network": "Facebook",
"campaign_id": "23847239847",
"campaign_name": "Summer Promo",
"click_timestamp": 1732171683565901
}
}
| Field | Type | Notes |
|---|---|---|
network |
String | Attribution source. Organic when no touchpoint was matched. |
campaign_id |
String | Campaign identifier from the touchpoint. |
campaign_name |
String | Campaign name from the touchpoint. |
subcampaign_id |
String | Sub-campaign identifier, when the partner provides one. |
subcampaign_name |
String | Sub-campaign name, when the partner provides one. |
creative_id |
String | Creative identifier, when the partner provides one. |
creative_name |
String | Creative name, when the partner provides one. |
passthrough |
String | Passthrough values carried on the touchpoint. |
match_type |
String | Match type reported for the touchpoint. Contact Singular if you need the value set. |
click_timestamp |
Integer | Click time in epoch microseconds. Divide by 1,000,000 for seconds. |
Response Codes & Errors
SESSION endpoint returns HTTP status codes and JSON responses indicating request success or failure.
Complete error documentation: S2S Response Codes & Error Handling
Testing & Validation
Verify S2S integration before production deployment using Singular SDK Console for real-time data validation.
Testing Procedure
End-to-End Validation
- Register Test Device: Obtain device advertising ID and add to Singular SDK Console
- Enable Console Logging: Add device identifier in SDK Console to capture test data
-
Use Development App ID:
Override app identifier
with development version (e.g.,
com.singular.app.dev) to separate test from production data - Launch App: Open app from terminated state to trigger session
- Validate Client Data: Confirm app sends all required Singular data points to your server
-
Verify Server Request:
Confirm your server sends
SESSION request to
https://s2s.singular.net/api/v1/launchwith all required parameters - Check SDK Console: Within seconds, SESSION event should appear in SDK Console
- Repeat Tests: Validate SESSION triggers on every app entry and foreground operation
Critical Verification: Confirm SESSION event occurs on app open/foreground BEFORE any EVENT requests. Invalid order causes attribution errors.
Success Indicator: If SESSION appears in SDK Console, you've completed successful end-to-end integration test!
Additional Resources
Testing Documentation
Comprehensive testing guide: S2S Integration Testing Guide