Quickstart (5 minutes)
Register an app install, send a heartbeat and open the feedback link in five minutes.
You need one thing: the campaign code of an open topic. Create the campaign in WTN Studio, open its Integrate tab and copy the code (it looks like PLS7Q2). It is public, like a publishable key, so it is safe to use from a terminal or an app.
The examples below use cURL and fill in placeholders. Use the Response switch on each step to see what comes back.
1. Register
The app announces itself. No API key is needed. Keep the deviceId and refreshToken from the answer.
# VALUES - replace these
API_BASE="https://api.wtn.live"
CAMPAIGN_CODE="YOUR_CAMPAIGN_CODE"
curl -sS -X POST "$API_BASE/api/v1/apps/register" \
-H 'Content-Type: application/json' \
-d '{
"campaignCode": "'"$CAMPAIGN_CODE"'",
"appId": "com.example.app",
"platform": "android",
"appVersion": "1.0.0",
"deviceModel": "Pixel 8",
"osVersion": "15",
"locale": "en-IN",
"language": "en",
"vendorDeviceId": "a1b2c3d4e5f60718",
"user": { "externalId": "user-1234", "email": "person@example.com", "phone": "+919876543210" }
}'
# Keep deviceId and refreshToken (secure storage); accessToken lives in memory. Leave "user" out for an anonymous
# device. A new refreshToken replaces the previous one.
# --- SERVER ONLY (never in the app): userHash proves externalId is yours (identity "verified") ---
# Your server sends it to the app, which adds it as user.userHash.
# printf '%s' "user-1234" | openssl dgst -sha256 -hmac "$WTN_LAUNCH_SECRET" -hex | sed 's/^.* //'
{
"deviceId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
"userId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5c",
"identity": "verified",
"accessToken": "EXAMPLE_ACCESS_TOKEN",
"accessTokenExpiresAt": "2026-10-20T10:00:00.000Z",
"refreshToken": "EXAMPLE_REFRESH_TOKEN",
"refreshTokenExpiresAt": "2027-04-17T10:00:00.000Z",
"heartbeatIntervalSecs": 900,
"installId": "EXAMPLE_INSTALL_ID",
"expiresAt": "2027-04-17T10:00:00.000Z"
}identity is anonymous, self_declared or verified. userId is null for an anonymous device.
2. Heartbeat
Call this on every app start. It returns a fresh accessToken.
# VALUES - replace these
API_BASE="https://api.wtn.live"
DEVICE_ID="DEVICE_ID_FROM_REGISTER"
REFRESH_TOKEN="REPLACE_WITH_REFRESH_TOKEN"
curl -sS -X POST "$API_BASE/api/v1/apps/heartbeat" \
-H 'Content-Type: application/json' \
-d '{"deviceId":"'"$DEVICE_ID"'","refreshToken":"'"$REFRESH_TOKEN"'"}'
# Run on every app start and every heartbeatIntervalSecs. Keep the new accessToken in memory.
# 401 DEVICE_AUTH_INVALID: the refresh token is no longer valid, register again.
{
"ok": true,
"accessToken": "EXAMPLE_ACCESS_TOKEN",
"accessTokenExpiresAt": "2026-10-20T10:00:00.000Z",
"refreshTokenExpiresAt": "2027-04-17T10:00:00.000Z",
"heartbeatIntervalSecs": 900,
"installId": "EXAMPLE_INSTALL_ID",
"expiresAt": "2027-04-17T10:00:00.000Z"
}{
"code": "DEVICE_AUTH_INVALID",
"title": "Device not recognised",
"description": "The refresh token is unknown, wrong, expired or revoked. Call register again."
}Every refusal has the same { code, title, description } shape (the title and description wording is an example).
3. Open the feedback page
Open this link in the phone's system browser (not an in-app WebView, because the page needs the microphone). The accessToken goes after the #, so it never reaches a server log.
# VALUES - replace these
SURVEY_BASE="https://survey.wtn.live"
CAMPAIGN_CODE="YOUR_CAMPAIGN_CODE"
LANG_CODE="en"
ACCESS_TOKEN="REPLACE_WITH_ACCESS_TOKEN"
# The token goes after # so it never reaches a server log or a Referer header.
echo "$SURVEY_BASE/p/$CAMPAIGN_CODE?lang=$LANG_CODE#dt=$ACCESS_TOKEN"
# Open this link in the phone's system browser (not a WebView).
https://survey.wtn.live/p/YOUR_CAMPAIGN_CODE?lang=en#dt=EXAMPLE_ACCESS_TOKENThe token sits after the # so it never reaches a server log. Optional check: GET /api/v1/public/pulse/<code>/access.
{
"requireSigned": false,
"state": "NOT_REQUIRED",
"refusal": null,
"language": "en"
}That is the whole loop. The person answers; the feedback is linked to the device (and the user, if you sent user fields in step 1).
4. See the result
In Studio, the Integrate tab lists the registered installs. From your server you can read the same data with an API key: see Server integration.
To check your whole integration automatically, see the test tool.