Documentation
Everything you need to go from sign-in to a paying customer.
Getting started
- Sign in with Google at lumencredits.com/signin and create an app in the dashboard. Its slug becomes your customer site:
your-slug.lumencredits.com. - Connect provider keys on the app's Edit page — Gemini, OpenAI, Claude, and/or Soniox. Keys are stored encrypted and never exposed to your customers.
- Connect PayPal — your merchant Client ID, secret, and webhook ID. Point the PayPal webhook at
https://lumencredits.com/api/_platform/tenant-paypal/webhook(one URL for all your apps). Customer payments land directly in your PayPal. - Set pricing on the app's Pricing page — what each model costs your customers in credits (see below) — and create credit offers on the Offers page.
- Share your storefront — customers sign in with Google, buy credits with PayPal, and call your app.
Your customer storefront
Every app gets a hosted site at your-slug.lumencredits.com with sign-in, pricing, checkout, and account pages. On the app's Edit page you control the headline, tagline, hero image (PNG/JPEG/WebP, max 2 MB — also used as the social-share image), and a markdown description. Toggle "List in the public directory" to appear on Apps on platform.
Pricing: tokens, uses, and credits
You price each provider modality per token (usd_per_token) and define a human-friendly "use" (tokens_per_use + a unit name — e.g. 1500 tokens = one minute of audio). Customers see prices in credits: credits = USD × credit display rate, which you set per app.
Important: offer amounts (amount_audio_seconds etc.) are counted in your pricing uses — if your audio unit is a minute, an offer granting 10 hours is 600, not 36000. The dashboard Pricing page has an "Update all prices" button that applies platform-published provider cost tables (current tables), keeping your units untouched.
The metered API
Base URL: https://api.lumencredits.com. Your customers mint API keys on their storefront account page; your app sends them as Authorization: Bearer <key> (or x-api-key). Every call is metered per token against your prices and deducted from that customer's credit balance — you never meter anything yourself.
| Endpoint | What it proxies |
|---|---|
/gemini/v1beta/*, /gemini/v1/* | Google Gemini REST (generateContent, streaming, images) |
/gemini/voice (WebSocket) | Gemini Live voice sessions (audio in/out, Opus or PCM) |
/openai/v1/* | OpenAI REST (chat completions, images) |
/claude/v1/* | Anthropic Claude REST (messages) |
/soniox/v1/*, /soniox/stt, /soniox/tts | Soniox speech-to-text and text-to-speech (REST + realtime WebSocket) |
/app/:slug/credits | The calling customer's credit balance |
Requests use the provider's native request/response format — point your existing SDK at the base URL above and swap the provider key for the customer's Lumen key. Working code: live API examples (sign-in required).
Letting users sign in from your app — device login
Device login gets a customer API key into your app without you ever handling passwords, and works everywhere — web, desktop, mobile, TVs, CLIs. Your app shows a link (or short code); the user approves it in their browser; your app receives the key over a server-sent-events stream.
The flow, step by step
- Generate a secret
device_codein your app — at least 20 characters; use 32 random bytes, base64url-encoded. This is the credential that claims the key later, so make it truly random and never show it to anyone. - Start the login:
POST https://api.lumencredits.com/app/<slug>/device/start { "device_code": "<random>", "redirect_uri": "https://yourapp.example/welcome", // optional "auto_redirect": true } // optionalredirect_uriis where the approver's browser continues after approving. It must be on your app's allowed redirect URIs list (Edit page) — exactly like OAuth; a URI not on the list is rejected with 403.auto_redirect: truemakes the login link carry&auto_redirect=1, so the browser continues there automatically instead of showing a "Continue" button.
Response:{ "user_code": "BCDF2345", "verification_uri": "https://lumencredits.com/apps/<slug>/device", "verification_uri_complete": "https://lumencredits.com/apps/<slug>/device?user_code=BCDF2345&auto_redirect=1", "interval": 5, "expires_in": 600 } - Show the user the login link — open
verification_uri_completedirectly, render it as a QR code, or tell them to visitverification_uriand type the shortuser_code. The code expires after 10 minutes. - The user approves on that page (Google sign-in). If you set a
redirect_uri, their browser then continues to your app — immediately withauto_redirect, otherwise via a "Continue to the app →" link. - Your app receives the key. Listen on SSE while you wait:
If the SSE connection drops, fall back to polling everyGET https://api.lumencredits.com/app/<slug>/device/events?device_code=<random> event: approved data: { "key": "lk_…", "key_prefix": "lk_ab…" } event: expiredintervalseconds:POST https://api.lumencredits.com/app/<slug>/device/poll { "device_code": "<random>" } → { "status": "pending" } | { "status": "approved", "key": "lk_…" } | { "status": "claimed" } | { "status": "expired" } - Store the
lk_key (e.g. localStorage / keychain) and use it for every metered API call and the voice socket. The key is delivered exactly once — a second poll returnsclaimed. Users can revoke keys from their storefront account page.
Security properties
- The API key never appears in any URL — it travels only over the SSE stream or poll response to the holder of the secret
device_code. redirect_uriis allowlist-validated server-side at/device/start, so approval links can never redirect users to a site you didn't approve.- Only a hash of
device_codeis stored; codes are single-use and expire in 10 minutes.
Working end-to-end code: the live API example (sign-in required) logs in with this exact flow.
What Lumen Credits costs you
Your customers pay you directly via PayPal — no revenue share. You pay a small metered platform fee for hosted infrastructure and token counting; current rates, the free signup grant, and a worked example are on the Pricing page. Your platform balance and usage are on the dashboard Billing page.
Troubleshooting
Rejected API calls (missing key, unpriced model, upstream provider errors) are recorded per app — see the Errors tab on each app in the dashboard. Billing or setup questions: [email protected].