Kist Capture App
The Capture App is the free Flutter client for Android and iOS. It hashes and signs every capture on-device, keeps the proof in a local ledger, and anchors proof metadata on Solana devnet through the hosted Kist API. Capture and signing need no account; anchoring needs active pay-as-you-go access.
Capture flow
- Capture a photo in the camera tab.
- The app computes the SHA-256 hash of the image bytes on the device.
- The hash is signed with the device's Ed25519 key, generated on first launch and stored in the platform keystore.
- The proof record is written to the local SQLite ledger with a local id before any network call.
- When a key and network are available, the ledger syncs to POST /api/v1/anchor and the proof is anchored on Solana devnet.
Offline-first
Captures are valid the moment they are signed, even with no network. Queued proofs stay on the device, retry with exponential backoff, and are never deleted by a failed sync — only by an explicit user action.
Send an array of records to /anchor/batch. Each entry returns its own status, so partial failures never block the rest.
Proof statuses
The app never shows a generic failure. Every proof is labelled with an actionable state: Signed locally, Queued for sync, Waiting for network, Syncing, Anchored on Solana, Waiting for API key, Waiting for access activation, API access disabled, Verification failed, Device enrollment failed, Retrying, or Sync failed.
- 401 (revoked or invalid API key) and 402 (access not active) stop the sync run and are never retried in a loop.
- 422 (the relayer rejected the signature) is permanent — the record is kept locally and marked Verification failed.
- 404 from /anchor means the device is not enrolled, so the app asks you to re-enroll before retrying.
- 429 and 5xx responses retry with exponential backoff, capped at 30 minutes.
Android and iOS builds
Android beta builds are published on the downloads page, together with the SHA-256 checksum of the exact file being served. They are release builds signed with the Kist beta key, not Google Play releases. There is no published iOS binary yet: iOS needs macOS, Xcode and Apple signing credentials, so the downloads page links to the source instead of a non-existent IPA.
Build it yourself
The Capture App source ships with the project. Clone the repository, then run it with the Flutter toolchain:
# Clone and run the Flutter appgit clone https://github.com/vigneshat-Git/Kistcd Kist/mobileflutter pub getflutter run
Device enrolment
Enrolment registers the device public key both locally and on-chain. It is idempotent — repeating it for the same key returns the same device id.
curl -X POST $KIST_API_BASE/devices/enroll \ -H "Authorization: Bearer $KIST_API_KEY" \ -d '{"publicKeyHex":"0x<devicePubkey>"}'