Dashboard
What happened each day — and whether it is trending up or down.
Daily Briefing
What moved, what to do, what to leave alone.
AI Briefing
Since yesterday
Needs attention
Running & next experiments
Experiments
Your ASA lab notebook — every theory, the change that tests it, and the verdict.
🌱 Learnings & rules adopted
The durable knowledge experiments leave behind — these constrain every future recommendation.
Campaigns
One row per campaign. Click a header to sort.
Purchases
Every RevenueCat purchase, newest first, with the campaign each is attributed to.
Keywords
Last 7 days · band by TTR · click a header to sort.
Search Terms
What people actually typed — the source of negative-keyword discovery.
Reports
Pick a dimension, a window and a timezone; filter it; sort any column. Save it and it comes back.
All reports
A saved report stores the query, never the numbers — opening one re-runs it against today's data.
Timeline
Every account change on one axis — so you can read results against the change that caused them.
Blended TTR, with change marker
Change log
AI Usage
Every call we made to a model, what it cost, and why.
Data & Sync
Where this account's data came from, and when.
Sync history
Every run this account has made — scheduled and manual alike.
The pipeline
Webhook deliveries
Every inbound RevenueCat delivery, newest first — and what Sift did with it.
REVENUECAT_WEBHOOK_SECRET shows up here, not only in the server logs. The
Payload of an accepted delivery is the body as received, secret-scrubbed. Rows past the
retention window are swept nightly.Remote Config
What the shipped app is told at launch — changeable without a release.
Live payload
Exactly what GET /api/v1/app-config returns for this account right now, from
the same assembler — so it cannot disagree with what the app receives. A disabled key is
absent, never null: absence means the binary uses its compiled default,
and {} is a complete, correct answer for an account with nothing turned on.
Loading…
Keys
Every key on the account, enabled or not — a staged-off key is the thing you came here to turn on, so hiding it would hide the workflow. Enabled is the staging mechanism: there is no draft/publish step, so turning a key on is what puts it in the payload above on every client's next launch.
Deleting a key does not restore a previous value — it reverts every client to its compiled default on the next launch, the same blast radius as a value change and easier to do by accident. Only the audit trail keeps the last value.
Add a key
The key and its type are immutable after creation — a key that changes type
mid-flight is a decoding crash in a binary already on people's phones that cannot be
patched. To change a type, add a new key and retire the old one. Type the value the way
JSON carries it: a string as-is with no quotes, an int or
float as a number, a json value as JSON.
Settings
Your account and password, the provider keys Sift holds, and the API reference for Claude Code.
Credentials
Provider API keys for the vault. The secret travels inbound only — it is verified against the provider before it is stored, and what comes back is a masked fingerprint, never the key itself. Submitting for a provider that already has a key rotates it.
Deleting destroys Sift's copy of the key; the row is kept for audit and can be replaced by adding the provider again. It does not revoke the key at the provider — do that in their console too.
API reference for Claude Code
A single Markdown file describing every Sift endpoint and the conventions a client needs — auth, money units, the report filter grammar, rate limits, and what it can and cannot do. Hand it to the Claude Code CLI so it can drive Sift over HTTP instead of guessing.