Concepts

Campaign code, API key, launch key, deviceId, userId, tokens and workspace scope.

On this page

Keys: what is public and what is secret

NamePublic?What it is forWhere it lives
Campaign codePublic (a publishable key)Names one feedback topic. Apps use it to register and to open the page. It can be re-issued; the old one can be disabled.In your app
API key (wtn_<prefix>_<secret>)SecretAuthenticates your server to /api/v1/channel/*. Carries scopes and a workspace allowlist. Shown once when it is created.Your server's secrets manager
Launch keySecretSigns a launch token (HS256) and computes userHash. A campaign has two active slots (current and next) so rotation never breaks a live app. Shown once.Your server only
Webhook secretSecretVerifies the signature on webhook deliveries. Shown once when you register the endpoint.Your server only

Anything inside an app binary can be extracted, so a secret never ships in an app.

Identity: device and user

  • deviceId: one app install. Issued by WTN as a UUID, unique within a workspace and appId. The app stores it (Keychain on iOS, EncryptedSharedPreferences on Android).
  • userId: one person. Issued by WTN, only when the app sends user.externalId, email or phone. It links one person's devices, so changing phones keeps the history.
  • identity says how much WTN can trust the user:
    • anonymous: no user fields were sent.
    • self_declared: the app named the user but did not prove it.
    • verified: your server computed userHash (HMAC-SHA256 of externalId with a launch-key secret) and the app sent it. A wrong hash is refused with 401 USER_HASH_INVALID.

Email and phone are stored encrypted and are never returned.

Tokens

  • refreshToken: proves the app owns its deviceId. Opaque, per device, long-lived (180 days by default) and renewed on every heartbeat. Store it securely.
  • accessToken: short-lived (24 hours by default). It travels in the page link's fragment so the feedback is linked to the device and user. Keep it in memory only.
Token lifecycle: register, heartbeat, open, expiry and refreshThe app registers and receives a deviceId, a refresh token and an access token. It sends a heartbeat on every start and every interval to get a fresh access token, and opens the page with the access token in the URL fragment. If the refresh token is unknown, revoked or expired, the heartbeat is refused with DEVICE_AUTH_INVALID and the app registers again.Your appsecure storageWTNapi.wtn.liveFeedback pagesurvey.wtn.liveregistercampaign code + optional userdeviceId, refreshToken, accessTokenstore the first twoheartbeatevery start + every intervalfresh accessTokenworks even if the old one expiredopen in the system browser#dt=<accessToken>Expired token: still opens, anonymousheartbeat, refresh token no longer valid401 DEVICE_AUTH_INVALIDcall register again

If the refresh token is unknown, revoked or expired, the heartbeat answers 401 DEVICE_AUTH_INVALID: call register again (the same user fields give back the same userId). An expired access token never blocks the person; the feedback is just kept anonymous.

Workspaces

Your API key belongs to a business that may run several client workspaces. If the key reaches exactly one, it is used automatically. If it reaches more than one, send X-WTN-Workspace: <workspace-id> on every data call, otherwise you get 400 WORKSPACE_REQUIRED. GET /api/v1/channel/orgs lists the workspaces your key may act on.

Open and signed access

By default a campaign is open: anyone with the link can leave feedback, protected by abuse limits. A campaign can instead require a signed launch: your server signs a short-lived, single-use token or asks the API for a one-time link, and an unsigned visit sees "open this from the app". See Server integration.