One glance.
Zero steps.

Checking your OpenRouter credit used to mean opening a browser tab, logging in, and navigating to Settings → Credits. Three steps for a number that should be one glance away. Now it's a widget.

ACCOUNT
$47.23

Nothing Phone 2a · Nothing OS 3.0

Device Nothing Phone 2a
OS Nothing OS 3.0
Android 8.0+ · API 26
License MIT
Build v2.0.1

The widget, alive in your browser.

Toggle display modes and slide the threshold. The dot and label respond in real time — exactly what the real widget does on-device.

ACCOUNT
$47.23
Alert threshold $5.00
$0$30$60

Balance above threshold — healthy

What the widget does.

01

Two display modes

Show your total account balance, or the cumulative usage of one API key. Switch modes from the config screen — the widget re-renders immediately.

02

Nothing OS aesthetic

Pure black background, thin 1dp border, 28dp rounded corners. VT323 dot-matrix numbers, uppercase muted labels — built to match Nothing OS.

03

Color-coded alert dot

Green when fine, Nothing-red when the balance drops below your custom threshold — or, in key mode, when usage exceeds it.

04

Manual refresh

Tap the refresh icon on the widget to trigger an immediate sync, with a live SYNC... status indicator while it fetches.

05

Background auto-refresh

WorkManager refreshes every 45 minutes when a network connection is available. Battery-friendly, doze-compatible.

06

Encrypted key storage

Your API key is persisted via EncryptedSharedPreferences, backed by the Android Keystore. Never logged. Never transmitted anywhere except OpenRouter.

07

Error resilience

If the network is down or the key is invalid, the widget keeps showing the last known good value with a small red indicator — instead of blanking out.

08

Resizable

Supports 2×1 compact and 2×2 full layouts. targetCellWidth="2" on Android 12+, with graceful fallbacks on older launchers.

09

Zero framework overhead

Classic RemoteViews and XML layouts. No Jetpack Glance, no Compose, no navigation library. Just the widget.

Four stages. One number.

01 / Config

MainActivity

Paste API key, validate against /api/v1/credits, choose mode, set threshold. Save to EncryptedSharedPreferences.

02 / Fetch

RefreshWorker

WorkManager dispatch on network connectivity. Calls /credits or /key based on displayMode. Updates cached values.

03 / Render

WidgetUpdater

Reads cached values, formats the number, chooses dot color based on mode + threshold. Wires PendingIntents for tap targets.

04 / Display

Home screen

RemoteViews renders the final widget — VT323 numbers, Nothing OS palette, live status dot.

Two API endpoints · Two modes · One glance

Calls worth defending.

01

RemoteViews, not Jetpack Glance

Glance is Google's recommended widget API, but its compiler plugin still produces opaque errors on OEM skins under AGP 8.5 + Kotlin 1.9. Nothing OS is one of the affected skins. RemoteViews with XML layouts is battle-tested across a decade of Android versions — stability over novelty.

02

Manual API key, not OAuth

OpenRouter's OAuth implementation does not support custom URI schemes as a callback_url. A full PKCE flow was built, tested, and confirmed to dead-end at the redirect step. The manual key path adds one copy-paste for the user and works unconditionally.

03

EncryptedSharedPreferences, not DataStore

DataStore is the modern replacement for SharedPreferences, but has no encrypted variant backed by the Android Keystore. EncryptedSharedPreferences is deprecated in Jetpack Security but remains the only officially supported path for Keystore-encrypted secrets without rolling custom crypto.

04

WorkManager, not AlarmManager

WorkManager is the only Android API that combines persistence across reboots, automatic network constraints, doze-mode compatibility, and exponential backoff in a single package. A foreground service would be disproportionate for a widget that updates twice an hour.

05

45 minutes, not 15

WorkManager's documented minimum is 15 minutes, but JobScheduler on Nothing OS and most OEM skins throttles jobs below 30 minutes when the device is idle. 45 minutes is the interval that reliably fires on schedule. Manual refresh is always immediate.

06

Cache the last known value

A widget that blanks out the moment Wi-Fi drops provides no value. The last known balance is almost always still relevant for the "do I have enough credit for this prompt" question, so it stays on screen with a red dot and an OFFLINE status line.

What it doesn't do — on purpose.

—

Workspace mode unavailable on personal accounts. OpenRouter only exposes /workspaces and /keys management endpoints to Business and Enterprise plans via a Provisioning API Key. On a personal Free or Standard account, that key does not exist, so workspace-level display modes are unreachable.

—

OAuth not supported. The OpenRouter OAuth flow does not accept custom URI schemes as a callback_url. A full PKCE implementation was built and tested — it dead-ends silently at the redirect step. This is an OpenRouter-side constraint.

—

No automatic refresh below 30 minutes. WorkManager's minimum periodic interval is 15 minutes, but Android throttles background work below 30 minutes on most devices. 45 minutes is the battery/accuracy tradeoff. Manual refresh always works immediately.

—

Single configuration per app. Multiple widget instances are supported, but they all share the same configuration. Per-widget display mode override is a tracked roadmap item.

Get it on your phone.

Two paths — grab the pre-built APK from GitHub Actions, or build it locally with Android Studio.

Path A

Pre-built APK

Download app-debug.apk from the latest green GitHub Actions run. Transfer to your phone, tap to install, enable "Install unknown apps" if prompted.

Path B

Build from source

Requires Android Studio with JDK 17, or the Android SDK and Gradle 8.7 on the command line. Clone the repo and assembleDebug.

01

Clone the repository

git clone https://github.com/mirconegri/openrouter-widget.git
02

Build the debug APK

./gradlew assembleDebug on macOS/Linux, or .\gradlew.bat assembleDebug on Windows PowerShell.