Mobile apps and the Activity Verification API
This guide is for apps such as the Helius Network app that run Proof-of-Life natively and verify movement sessions.
1. Create a site that allows native callers
node scripts/create-site.js --name "Helius app" --hosts heliusnetwork.app --native --plan growth
Native apps send no Origin header. --native allows that for this site key only. Add --uniqueness-threshold 0.7 if you want unique to need more evidence than the default 0.6.
2. Liveness, or the full ceremony
- Liveness only (
HeliusPoL.liveness()): a motion challenge, no passkey, no uniqueness. Use it before a reward claim or a sensitive action when the user is already signed in to your app. Your server checks the token withsiteverify;levelisliveness. - Full PoL Gate ceremony (
HeliusPoL.gate()): motion challenge, device passkey, optional location cell. Returns a single-use site token plus a native pass to keep in secure storage. The native pass is pairwise, works only for your site key, and lasts 7 days by default (POL_NATIVE_PASS_TTL_DAYS).siteverifyreturnsuniqueness_confidenceandunique.
3. Activity sessions
const run = await pol.startActivity('walking');
// ... later
const result = await run.stop();
if (result.verified) await yourServer.claim(result.token);
Your server:
const v = await fetch('https://api.heliusnetwork.app/v1/siteverify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret: process.env.POL_SECRET, response: token }),
}).then((r) => r.json());
// v.level === 'activity', v.activity = { type, km, dur_s, cf }. The token is single use.
If your backend already collects GPS traces (for example from a background location task), verify server to server and get a score in the same call:
const r = await fetch('https://api.heliusnetwork.app/v1/activity/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.POL_SECRET,
session: { activity: 'running', points, accel, device },
scoring: { reputationLevel: 'trusted', earnedToday: 3.2, totalUsers: 12000 },
}),
}).then((r) => r.json());
// r.verified, r.confidence, r.hard, r.soft, r.layers, r.summary, r.score.reward
Delete the trace on your side once you have the result. The verifier keeps none of it.
4. Combine the signals
A typical reward rule:
| Check | Required |
|---|---|
siteverify of the user's pass: success |
yes |
unique |
yes for rewards; no for free features |
activity verified and confidence |
0.5 or more (the default pass), 0.8 or more for large rewards |
| daily cap | enforced by score.reward when you pass earnedToday |
5. Co-verification at events
At a club meeting or a beach clean-up, established members can vouch for new members in person: one opens a vouch and shows the code, the other joins, and both do the same challenge within 60 seconds. This is the fastest honest way for a new member to reach unique: true. Each member can vouch for 3 people a week.
Proof-of-Life is in early access. Request keys, read the API reference or the privacy notice.