本参考文章列出了 Singular 为 S2S 集成提供的 API 端点。
- 有关创建 S2S 集成的分步指南,请参阅《Singular 服务器到服务器(S2S)集成指南》。
- 如需了解通过 API 从 Singular 提取报告的相关信息,请参阅《报告 API 参考》。
注意:服务器到服务器集成仅适用于企业客户。
更新 [2021 年 11 月]:现在应通过会话通知端点(而非事件通知)报告安卓安装引用源。 这样,当用户打开应用程序时,Singular 就能立即获得安装引用源,并遵循谷歌的最佳实践。更多信息,请参阅发送 Google Play 安装推荐器(安卓)。
身份验证和状态代码
任何对 S2S API 的调用都必须包含您的 SDK 密钥。要获取 SDK 密钥,请登录 Singular 并转到 "开发工具 > SDK 集成 > SDK 密钥"。
如果调用 S2S API 成功,则返回的HTTP 状态代码为 200。任何其他代码都意味着您应该重试调用。
Singular S2S API 端点列表
以下是可用的 API 端点:
会话通知 | GET | https://s2s.singular.net/api/v1/launch | 向 Singular 报告新会话。 |
事件通知 | GET | https://s2s.singular.net/api/v1/evt | 向 Singular 报告应用内事件。 |
会话通知端点
GET | https://s2s.singular.net/api/v1/launch |
使用会话通知端点向 Singular 报告会话。
所需会话参数
参数 | 描述 | 支持的平台 | 示例 |
---|---|---|---|
a | 奇异 SDK 密钥。 | iOS, Android, PC, Console |
your_org_name_sh868sdjv |
p | 以下平台之一: Android, iOS, PC, Xbox, Playstation, Nintendo, MetaQuest or CTV |
iOS, Android, PC, Console |
安卓 |
i | 应用程序的软件包名称(Android)或软件包 ID(iOS)。 | iOS, Android, PC, Console |
com.singular.app |
ip | 设备的 IP。仅限 IPV4;不支持 IPV6。 | iOS, Android, PC, Console |
172.58.29.235 |
ve | 会话时设备的操作系统版本。 | iOS, Android, PC, Console |
9.2 |
install_ref | 谷歌安装推荐人信息 | Android | 了解更多 |
meta_ref | 元安装推荐人信息 | Android | 了解更多 |
asid | 应用程序集 ID(适用于 Android 12+ 设备) | Android | 了解更多 |
ma | 设备硬件的品牌,通常是面向消费者的名称(如三星、LG、苹果)。该参数必须与型号参数一起使用。 | iOS, Android | samsung |
mo | 设备硬件的型号(如 iPhone 4S、Galaxy SIII)。该参数必须与型号参数一起使用。 | iOS, Android | SM-G935F |
lc | 设备的 IETF 本地标签,使用下划线分隔的双字母语言和国家代码。 | iOS, Android | en_US |
bd | 设备的构建(URL 编码 | iOS, Android | Build%2F13D15 |
openuri | 如果应用程序是通过任何深度链接/通用链接/应用程序链接打开的,编码后的深度链接 URL 值 | iOS, Android | myapp%3A%2F%2Fhome%2Fpage%3 Fqueryparam1%3D value1%26queryparam2%3 Dvalue2 |
idfa | 仅适用于 iOS 应用程序。带破折号的大写原始广告 ID。 | iOS | DFC5A647-9043-4699-B2A5-76F03A97064B |
idfv | 仅适用于 iOS 应用程序。带破折号的大写原始IdentifierForVendor。 | iOS | 21DB6612-09B3-4ECC-84AC-B353B0AF1334 |
aifa | 带破折号的小写原始 Google 广告 ID。 | Android (Google Play) | 8ecd7512-2864-440c-93f3-a3cabe62525b |
asid |
应用程序设置 ID(适用于 Android 12+ 设备)。如果没有 Google 广告 ID (aifa),则应发送此标识符。了解更多信息 |
Android (Google Play) | edee92a2-7b2f-45f4-a509-840f170fc6d9 |
amid |
带破折号的亚马逊广告 ID。适用于亚马逊设备。 |
Android (Amazon) | df07c7dc-cea7-4a89-b328-810ff5acb15d |
oaid | Android | 01234567-89abc-defe-dcba-987654321012 | |
andi |
仅适用于非 Google Play Android 应用程序。小写原始 Android ID。 只有在没有其他设备标识符的情况下,才应发送此标识符。 |
Android | fc8d449516de0dfb |
sdid |
电脑/控制台: 客户端生成的 UUIDv4 代表唯一的应用程序安装。 |
PC, Console | 40009df0-d618-4d81-9da1-cbb3337b8dec |
dnt | 如果启用了 "不跟踪",则通过 1;如果禁用了 "不跟踪",则通过 0。 | iOS, Android | 1 |
app_v | 应用程序版本 | iOS, Android | 1.2.3 |
install_source |
Android 上的安装源软件包名称,例如:"com.android.vending"。要检索此值,请使用InstallSourceInfo.getInitiatingPackageName()
电脑上的安装商店,支持/建议值为: steam, epic, microsoftstore, humblestore, gog, selfdistributed |
Android, PC |
Android: com.vending.android (Android) steam (PC) |
install_receipt | 安装时收到的收据。了解如何在iOS 安装收据中检索该收据 | iOS | MIISqwYJKoZI...cNqts0jvcNvPcK7 yuj0KhJ9nTTQ54kDKfReihzc6aw== |
install | 安装标志。如果会话是安装应用程序后的第一个会话,则为'true'。否则为'false'。需要重新安装跟踪功能。 | iOS, Android, PC, Console |
false |
install_time | 首次安装应用程序的时间(UNIX 时间)。要检索此值,请使用平台上的链接。 | iOS, Android | 1510040127 |
update_time | 上次更新应用程序的时间(UNIX 时间)。要检索此值,请使用平台上的链接。 | iOS, Android | 1510040127 |
ddl_enabled | 延迟深度链接标志。如果服务器希望返回延迟的深度链接 URL,则为 "true"。否则为'false'。有关详细信息,请参阅我们的 "延迟深度链接 "部分 | iOS, Android | true |
singular_link_resolve_required | 用于解析奇异短链接。发送时必须在 "openuri "中包含奇异短链接的值。请参阅短链接处理。 |
iOS, |
true |
att_authorization_status * |
适用于 iOS 14 及以上版本。应用程序跟踪透明度授权状态。 支持的值有
|
iOS | 3 |
* 注意: 从 iOS 14.5 开始,访问 IDFA 需要使用应用程序跟踪透明度 (ATT) 提示。即使您不执行 ATT 提示,我们也要求您将 ATT 授权状态传递给 Singular(值为 "0",表示 "未确定")。
可选会话参数
参数 | 描述 | 支持的平台 | 示例 |
---|---|---|---|
custom_user_id | User ID | iOS, Android, PC, Console |
123456789abcd |
n | 用户界面中显示的应用程序的可读名称。 | iOS, Android, PC, Console |
MyCoolApp |
utime | 以 10 位数 UNIX 时间表示的会话时间。 | iOS, Android, PC, Console |
1483228800 |
umilisec | 会话时间(毫秒) 13 位 UNIX 时间。 | iOS, Android, PC, Console |
1483228800000 |
dntoff | 如果启用了 "不跟踪",则通过 0;如果禁用了 "不跟踪",则通过 1。 | iOS, Android | 0 |
c | 连接类型 "wifi "或 "运营商"。 | iOS, Android | wifi |
cn | 互联网提供商的运营商名称。 | iOS, Android | 康卡斯特 |
use_ip | 从 HTTP 请求中提取 IP 字段,而不是 "ip "字段。 不要与 IP 参数一起使用。 | iOS, Android, PC, Console |
true |
fcm | Firebase 云消息设备令牌。安卓卸载跟踪需要 | Android | bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvD MExUdFQ3P1 |
gcm | Google 云信息设备令牌。安卓卸载跟踪(传统)需要 | Android | bk3RNwTe3H0CI2k_ HHwgIpoDKCIZvvDM ExUdFQ3P1 |
apns_token | Apple 推送通知服务设备令牌。iOS 卸载跟踪需要 | iOS | b0adf7c9730763f88e1a048e28c68a9f806ed032fb522deb...ff5bfba010a9b052 |
ua | 设备的用户代理 | iOS, Android, PC, Console |
Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 |
attribution_token | 用于 iOS 14.3 及以上版本的 Apple Search Ads 属性。 该值可通过AdServices 框架获取。 了解如何通过AdServices 实施 Apple Search Ads获取该值。 | iOS | G9i5hC8lQJeGOfmS+MFycll/02...AAABBEQQBQA= |
skan_conversion_value | 此会话通知时的最新 SKAdNetwork 转换值(了解有关 SKAdNetwork 实施的更多信息)。 | iOS | 0 - 63 |
skan_first_call_timestamp | 首次调用底层 SkAdNetwork API 的 Unix 时间戳(要了解有关 SKAdNetwork 实现的更多信息,请阅读此处 | iOS | 1483228800 |
skan_last_call_timestamp | 此会话通知时最近一次调用底层 SkAdNetwork API 的 Unix 时间戳(要了解有关 SKAdNetwork 实现的更多信息,请阅读此处 | iOS | 1483228800 |
global_properties | 您最多可以定义 5 个全局属性。每个属性的键和值最长可达 200 个字符。如果您传递的属性名称或值较长,则会被截断为 200 个字符。值必须是 URLEncoded JSON 对象。 | iOS, Android, PC, Console |
%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D |
data_sharing_options |
表明最终用户同意共享信息。如果设置了该值,则该值必须持续存在,并在用户随后的每次 /launch 和 /evt 请求中传递。 通过 "limit_data_sharing":false 表示用户同意(选择加入)共享其信息。 如果用户拒绝,则输入 "limit_data_sharing":true。 |
可选项 |
%7B%22limit_data_sharing%22%3Atrue%7D |
API 调用示例
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
params = {
'a': SDK_KEY,
'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',
'andi': 'fc8d449516de0dfb',
'utime': 1483228800,
'dnt': 0,
'install':'true',
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'fcm':'bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1',
'app_v':'1.2.3',
'openuri':'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1',
'ddl_enabled':'false',
'install_source': 'com.android.vending',
'install_time': 1510040127,
'update_time': 1510090877,
'custom_user_id': '123456789abcd',
'global_properties': json.dumps({"key1":"value1","key2":"value2"})
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/launch?aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&andi=fc8d449516de0dfb&p=Android&a=SDK_KEY&i=com.singular.app&ip=10.1.2.3&ve=9.2&dnt=0&n=MyCoolApp&dnt=0&c=wifi&cn=Comcast&lc=en_US&bd=Build%2FMMB29K&ma=samsung&mo=SM-G935F&custom_user_id=123456789abcd&global_properties=%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D
#GET
curl --request GET \
--url 'https://s2s.singular.net/api/v1/launch?aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&andi=fc8d449516de0dfb&p=Android&a=SDK_KEY&i=com.singular.app&ip=10.1.2.3&ve=9.2&dnt=0&n=MyCoolApp&dnt=0&c=wifi&cn=Comcast&lc=en_US&bd=Build%2FMMB29K&ma=samsung&mo=SM-G935F&custom_user_id=123456789abcd&global_properties=%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D'
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import org.json.JSONObject; //From java-json.jar
public class SingularSessionEvent {
public static void main(String[] args) {
try {
SingularSessionEvent.postEvent();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void postEvent() throws Exception {
String singularSDKKey = "sdk key from developer tools > sdk keys";
String singularSessionEndpoint = "https://s2s.singular.net/api/v1/launch";
Map < String, Object > params = new LinkedHashMap < > ();
params.put("a", singularSDKKey);
params.put("p", "Android");
params.put("i", "com.singular.app");
params.put("ip", "10.1.2.3");
params.put("ve", "9");
params.put("ma", "samsung");
params.put("mo", "SM-A705MN");
params.put("lc", "en_US");
params.put("aifa", "8ecd7512-2864-440c-93f3-a3cabe62525b");
params.put("andi", "fc8d449516de0dfb");
params.put("utime", 1483228800);
params.put("dnt", 0);
params.put("install", "true");
params.put("n", "MyCoolApp");
params.put("bd", "Build/13D15");
params.put("fcm", "bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1");
params.put("app_v", "1.2.3");
params.put("openuri", "myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1");
params.put("ddl_enabled", "false");
params.put("install_source", "com.android.vending");
params.put("install_time", 1510040127);
params.put("update_time", 1510090877);
params.put("custom_user_id", "123456789abcd");
params.put("global_properties", "%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D");
URL url = new URL(singularSessionEndpoint); StringBuilder postData = new StringBuilder(); for (Map.Entry < String, Object > param: params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(URLEncoder.encode(param.getKey(), "UTF-8")); postData.append('='); postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8")); } byte[] postDataBytes = postData.toString().getBytes("UTF-8"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); conn.setDoOutput(true); conn.getOutputStream().write(postDataBytes); Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); StringBuilder sb = new StringBuilder(); for (int c; (c = in .read()) >= 0;) sb.append((char) c); // Print Singular JSON Response String response = sb.toString(); JSONObject singularResponse = new JSONObject(response.toString()); if (singularResponse.length() > 1) { System.out.println("status: " + singularResponse.getString("status")); System.out.println("reason: " + singularResponse.getString("reason")); // Handle Reason } else { System.out.println("status: " + singularResponse.getString("status")); } } }
事件通知端点
GET | https://s2s.singular.net/api/v1/evt |
使用此端点可报告应用程序中除会话外发生的任何事件。
所需事件参数
参数 | 描述 | 支持的平台 | 示例 |
---|---|---|---|
n |
事件名称。限制:最多 32 个 ASCII 字符 建议使用Singular 的标准事件命名规范。 |
iOS, Android, Web, PC, Console |
sng_add_to_cart |
a | Singular SDK 密钥。 | iOS, Android, Web, PC, Console |
a42be1d8119389dd36c7_acbeaf6abcd8 |
p | 以下平台之一: Android, iOS, Web, PC, Xbox, Playstation, Nintendo, MetaQuest or CTV |
iOS, Android, Web, PC, Console |
Android |
i | 移动应用程序的软件包名称(Android)或软件包 ID(iOS),或 WebSDK 中的 ProductID。 | iOS, Android, Web, PC, Console |
com.yourcompany.app |
ip | 设备的 IP。仅限 IPV4;不支持 IPV6。 | iOS, Android, Web, PC, Console |
172.58.29.235 |
idfa | 仅适用于 iOS 应用程序。带破折号的大写原始广告 ID。 | iOS | DFC5A647-9043-4699-B2A5-76F03A97064B |
idfv | 仅适用于 iOS 应用程序。带破折号的大写原始IdentifierForVendor。 | iOS | 21DB6612-09B3-4ECC-84AC-B353B0AF1334 |
aifa | 带破折号的小写原始 Google 广告 ID。 | Android (Google Play) | 8ecd7512-2864-440c-93f3-a3cabe62525b |
asid | 应用程序设置 ID(适用于 Android 12+ 设备)。如果没有 Google 广告 ID (aifa),则应发送此标识符。了解更多信息 | Android (Google Play) | edee92a2-7b2f-45f4-a509-840f170fc6d9 |
amid | 带破折号的亚马逊广告 ID。适用于亚马逊设备。 | Android (Amazon) | df07c7dc-cea7-4a89-b328-810ff5acb15d |
oaid | 带破折号的开放广告 ID 通常用于中国国内设备。可使用集成的 MSA SDK 或华为 OAID SDK | Android | 01234567-89abc-defe-dcba-987654321012 |
andi |
仅适用于非 Google Play Android 应用程序。小写原始 Android ID。 只有在没有其他设备标识符的情况下,才应发送此标识符。 |
Android | fc8d449516de0dfb |
sdid |
网络:由 Singular WebSDK 提供的 UUIDv4 设备 ID了解更多 电脑/控制台:客户端生成的 UUID,代表游戏的唯一安装。 |
Web, PC, Console | 40009df0-d618-4d81-9da1-cbb3337b8dec |
ve | 事件发生时设备的操作系统版本。 | iOS, Android, Web, PC, Console |
9.2 |
att_authorization_status * |
应用程序跟踪透明度授权状态。 适用于 iOS 14 及以上版本。 支持的值:
|
iOS | 3 |
* 注意:从 iOS 14.5 开始,要访问设备的 IDFA,必须使用应用程序跟踪透明度 (ATT) 提示。即使您不执行 ATT 提示,我们也要求您将 ATT 授权状态传递给 Singular(值为 "0",表示 "未确定")。
可选事件参数
参数 | 描述 | 支持的平台 | 示例 |
---|---|---|---|
custom_user_id | User ID | iOS, Android, Web, PC, Console |
123456789abcd |
utime | 以 10 位数 UNIX 时间表示的会话时间。 | iOS, Android, Web, PC, Console |
1483228800 |
umilisec | 会话时间(毫秒) 13 位 UNIX 时间。 | iOS, Android, Web, PC, Console |
1483228800000 |
use_ip | 从 HTTP 请求中提取 IP 字段。如果设置为 true,则无需提供ip参数。 | iOS, Android, Web, PC, Console |
true |
e |
JSON 格式的自定义事件属性。 强烈建议使用Singular 的标准事件属性命名规范。 |
iOS, Android, Web, PC, Console |
%7B%22sng_attr_content_id%22%3A5581%2C sng_attr_content%22%3A%22XBox%22%2C%22 sng_attr_content_type%22%3A%22electronics%22%7D |
global_properties | 您最多可以定义 5 个全局属性。每个属性的键和值最长可达 200 个字符。如果传递的属性名称或值较长,则会被截断为 200 个字符。值必须是 URLEncoded JSON 对象。 | iOS, Android, Web, PC, Console |
%7B%22key1%22%3A%22value1%22 %2C%22key2%22%3A%22value2%22%7D |
data_sharing_options |
表明最终用户同意共享信息。如果设置了该值,则该值必须持续存在,并在用户随后的每次 /launch 和 /evt 请求中传递。 通过 "limit_data_sharing":false 表示用户同意(选择加入)共享其信息。 如果用户拒绝,则输入 "limit_data_sharing":true。 |
可选项 |
%7B%22limit_data_sharing%22%3Atrue%7D |
skan_conversion_value | 事件通知时的最新 SKAdNetwork 转换值(要了解 SKAdNetwork 实现的更多信息,请阅读此处 | iOS | 0 - 63 |
skan_first_call_timestamp | 首次调用底层 SkAdNetwork API 的 Unix 时间戳(要了解有关 SKAdNetwork 实现的更多信息,请阅读此处 | iOS | 1483228800 |
skan_last_call_timestamp | 该事件通知时最近一次调用底层 SkAdNetwork API 的 Unix 时间戳(要了解有关 SKAdNetwork 实现的更多信息,请阅读此处 | iOS | 1483228800 |
收入事件参数
参数 | 说明 | 支持的平台 | 示例 |
---|---|---|---|
is_revenue_event | 是否为收入事件。如果事件名称为 __iap__ 或提供的金额不为零,则可以省略。 | iOS, Android, Web, PC, Console | True |
amt | 货币金额。应与 cur 参数一起使用。 | iOS, Android, Web, PC, Console | 2.51 |
cur | ISO 4217三字母货币代码。应与 amt 参数一起使用。 | iOS, Android, Web, PC, Console | EUR |
purchase_receipt | 从购买中收到的收据。请参阅下面的说明,了解如何从安卓和iOS 系统获取收据。 | iOS, Android |
iOS: Android: |
receipt_signature | 用于签署购物收据的签名 | Android | TyVJfHg8OAoW7W4wuJt... 5agEDMnNXvhfrw== |
purchase_product_id | 产品 SKU 识别码 | iOS, Android, Web, PC, Console |
com.example.product |
purchase_transaction_id | 交易标识符 | iOS, Android, Web, PC, Console |
iOS: 380000123004321 Android: GPA.1234-1234- 1234-12345 |
示例 API 调用
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
EVENT_URL = 'https://s2s.singular.net/api/v1/evt'
params = {
'n': 'levelup',
'e': json.dumps({"level": "10"}),
'a': SDK_KEY,
'p': 'Android',
'i': 'com.yourcompany.app',
'ip': '10.1.2.3',
'aifa': '8ecd7512-2864-440c-93f3-a3cabe62525b',
'andi': 'fc8d449516de0dfb',
'utime': 1483228800,
'custom_user_id': '123456789abcd',
'global_properties': json.dumps({"key1":"value1","key2":"value2"})
}
result = requests.get(EVENT_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/evt?aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&andi=fc8d449516de0dfb&p=Android&a=SDK_KEY&i=com.singular.app&n=levelup&e=%7B%22level%22%3A%20%2210%22%7D&ip=10.1.2.3&custom_user_id=123456789abcd&global_properties=%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D
#GET
curl --request GET \
--url 'https://s2s.singular.net/api/v1/evt?aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&andi=fc8d449516de0dfb&p=Android&a=SDK_KEY&i=com.singular.app&n=levelup&e=%7B%22level%22%3A%20%2210%22%7D&ip=10.1.2.3&custom_user_id=123456789abcd&global_properties=%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D'
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import org.json.JSONObject; //From java-json.jar
public class SingularCustomEvent {
public static void main(String[] args) {
try {
SingularCustomEvent.postEvent();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void postEvent() throws Exception {
String singularSDKKey = "sdk key from developer tools > sdk keys";
String singularEventEndpoint = "https://s2s.singular.net/api/v1/evt";
Map < String, Object > params = new LinkedHashMap < > ();
params.put("a", singularSDKKey);
params.put("n", "sign_up");
params.put("e", "{\"user_id\":\"1234\"}");
params.put("p", "Android");
params.put("i", "com.singular.app");
params.put("ip", "10.1.2.3");
params.put("aifa", "8ecd7512-2864-440c-93f3-a3cabe62525b");
params.put("utime", 1483228800);
params.put("andi", "fc8d449516de0dfb");
params.put("custom_user_id", "123456789abcd");
params.put("global_properties", "%7B%22key1%22%3A%22value1%22%2C%22key2%22%3A%22value2%22%7D");
URL url = new URL(singularEventEndpoint); StringBuilder postData = new StringBuilder(); for (Map.Entry < String, Object > param: params.entrySet()) { if (postData.length() != 0) postData.append('&'); postData.append(URLEncoder.encode(param.getKey(), "UTF-8")); postData.append('='); postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8")); } byte[] postDataBytes = postData.toString().getBytes("UTF-8"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); conn.setDoOutput(true); conn.getOutputStream().write(postDataBytes); Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); StringBuilder sb = new StringBuilder(); for (int c; (c = in .read()) >= 0;) sb.append((char) c); // Print Singular JSON Response String response = sb.toString(); JSONObject singularResponse = new JSONObject(response.toString()); if (singularResponse.length() > 1) { System.out.println("status: " + singularResponse.getString("status")); System.out.println("reason: " + singularResponse.getString("reason")); // Handle Reason Code } else { System.out.println("status: " + singularResponse.getString("status")); } } }