Ship your app with no secrets in the binary.

Grantiva verifies every install with App Attest and issues a JWT your backend checks against our public keys. No API keys to embed, leak, or rotate. Flags, analytics, feedback, and experiments run on that same verified identity. One Swift package.

Try for freeiOS 18+ · macOS 15+ · SPM
Two calls to production.Swift
import Grantiva

let grantiva = Grantiva(teamId: "ABCDE12345")
let result = try await grantiva.validateAttestation()

// Your backend verifies the JWT against
// https://api.grantiva.io/.well-known/jwks.json

Works in the simulator too. Unattested requests are marked so you can tell them apart.

01 · The foundation

Every feature runs on a verified device.

App Attest proves a request comes from your app, signed by Apple, tied to your Bundle ID and Team ID. Grantiva validates the attestation and issues a JWT. Every feature on this page keys off that identity. Flags can't be flipped by resigned builds. Analytics counts real installs. Feedback comes from devices that exist.

  • Attestation validated server side, JWT issued per device
  • Your backend verifies tokens against our published JWKS
  • Simulator and development builds fall back to API key auth, marked unattested
How attestation works →
Incoming requestsLive
iPhone 16 Pro · 18.6      VERIFIED
iPhone 14 · 17.5          VERIFIED
Simulator · arm64         UNATTESTED
iPad Air · 18.6           VERIFIED
Resigned build            BLOCKED
02 · Feature Flags

Roll out, target, and kill features without shipping. Changes reach devices over a live stream, not on next launch.

03 · Feedback & Support

Bug reports arrive with device info and build number attached. Reply to the user in app, from the dashboard.

04 · Analytics

Events, funnels, and retention counted on attested devices. No IDFA, no fingerprinting, nothing new on your privacy label.

05 · Risk Scoring

Every attestation returns a score from 0 to 100. Gate sensitive actions on it.

06 · A/B Testing

Experiments ride the flag system. Sticky variants per device, results in the dashboard.

07 · No API keys in your app

Your app holds no secrets. Devices prove themselves to Grantiva, your backend verifies the JWT against our public keys. A scraped binary gives an attacker nothing to steal.

02 · Feature Flags

Ship dark. Launch when ready.

Define flags in the dashboard. Target by app version, locale, or segment. Roll out by percentage. When something breaks, turn it off from your phone. No release, no review.

  • Percentage rollouts and per-segment targeting
  • Changes stream to devices live over SSE
  • Your inline defaults apply when the network is down, so the app keeps working
let newPaywall = try await grantiva.flags.boolValue(
    for: "new_paywall", default: false
)
03 · Feedback & Support

Bug reports with the context attached.

Prebuilt feedback screens drop into your app. Every report arrives with device info and build number. Users vote on feature requests. Support threads run two ways, in app, so you never ask "what version are you on" again.

  • Feature requests with voting, built in
  • Device and build info attached to every report
  • Two-way support threads from the dashboard
grantiva.feedback.present()
04 · Analytics

Counts you can trust, and nothing to disclose.

Events, funnels, and retention, counted on attested devices. Emulator farms and resigned builds never make it into your numbers. No IDFA, no fingerprinting, no third-party trackers.

  • Funnels and retention out of the box
  • Attested devices only, so bots don't inflate your charts
  • Export your raw events any time
grantiva.track("checkout_completed", [
    "plan": "pro"
])
05 · Risk Scoring

A number, not a boolean.

Each attestation returns a risk score from 0 to 100, built from jailbreak status, device integrity, and attestation history. You set the thresholds. Gate checkout at one number, require step-up at another, block at a third.

  • Score returned with every attestation, no extra call
  • Signals itemized in the dashboard, not a black box
  • Webhook alerts when a device crosses your threshold
let result = try await grantiva.validateAttestation()

if let risk = result.deviceIntelligence.riskScore, risk > 40 {
    requireStepUp()
}
06 · A/B Testing

Experiments without app review.

Variants assign from the dashboard and stay sticky per device. Wire them to your events and read the results where you defined the test. Attested assignment means one device is one participant, so nobody games your sample.

  • Variants sticky per attested device
  • Results tied to your analytics events
  • Start and stop tests without a release
let price = try await grantiva.experiment("paywall_price")
showPaywall(price: price.stringValue)
07 · No API Keys

A scraped binary gives an attacker nothing.

Most apps ship with secrets because their backend needs some way to trust the client. Grantiva replaces that. The device proves itself with App Attest, we issue a short-lived JWT, and your backend verifies it against our published JWKS. Keys never exist on the client, so they can't leak from it.

  • Zero secrets in the binary, nothing to extract
  • Short-lived JWTs, verified by your backend with any JWT library
  • Custom claims put your own data in the token, so one check does two jobs
var request = URLRequest(url: api.checkout)
request.setValue("Bearer \(grantiva.getCurrentToken() ?? "")",
                 forHTTPHeaderField: "Authorization")
Before you ship · Visual Regression Testing

Catch UI breaks in CI, not in reviews.

Everything above runs in your shipped app. This one runs before it ships. Snapshot every screen in CI, diff against your baseline, and see failures as a check on the PR. Baselines per device size and locale.

How VRT works →
$ grantiva snapshot --scheme App

  checkout-flow    2 diffs
  onboarding       clean
  settings         clean

The two questions everyone asks.

"One vendor across my whole stack?"

Fair question, so here is exactly what happens if Grantiva is unreachable. Flags return your inline defaults, and cached values apply within their TTL, so your app keeps working. Analytics events wait and send later. Attested JWTs keep working until they expire, so your backend keeps accepting real devices. Feedback screens queue their reports.

Your data is yours. Export raw events and feedback any time. Our status page is public, with history: grantiva.instatus.com.

"Why not LaunchDarkly plus PostHog plus Instabug?"

You can, and for some teams that is right. Here is the case for one SDK. Three SDKs each add launch time, binary size, and a privacy-label entry. And they cannot share an identity: a segment you define in Grantiva targets flags, filters analytics, and routes feedback, because all three see the same attested device.

What we don't do: crash reporting. If you need Sentry for crashes, keep Sentry. It runs fine next to Grantiva.

Proof

Built in the open, by someone you can check on.

Grantiva is built by Kyle Browning, author of APNSwift, the Swift APNs library used across the server-side Swift ecosystem. The backend is Swift and Vapor. We use the tools you use, and Grantiva runs on Grantiva: the flags, analytics, and feedback on this site go through the same SDK we ship.

Status pageGitHubDocs
Pricing

Flat price. Every feature. No overages.

Priced by monthly active devices. Every tier gets every product. When you grow past a tier we email you, nothing breaks and nothing surprise-bills.

Free
$0
1,000 monthly active devices
  • ✓ 2 apps
  • ✓ Every feature included
  • ✓ No card required
Start free
Pro
$29/mo
25,000 monthly active devices
  • ✓ 3 apps
  • ✓ Custom claims
  • ✓ Risk scoring
  • ✓ Flag targeting
Try for free
Business
$149/mo
250,000 monthly active devices
  • ✓ 10 apps
  • ✓ Fraud rules
  • ✓ Webhooks
  • ✓ Unlimited VRT
Try for free
Enterprise
$899/mo
Unlimited devices and apps
  • ✓ SSO and SAML
  • ✓ Dedicated support
  • ✓ Still flat
Contact us

Verified from the first request.

Try for free
Free tier, no card, ten minutes to your first attested device