Documentation
Quickstart and API reference · Last updated: August 6, 2026
MyAppToken is a reverse proxy: your app calls the provider's native API through
api.myapptoken.com, and the proxy injects your provider API key
server-side. The integration is a base-URL swap plus a lightweight per-user token.
Quickstart
1. Create an app and a service
Sign in to the dashboard with Google
and create an application — it gets a UUID app ID, shown in the dashboard (e.g.
550e8400-e29b-41d4-a716-446655440000). Then add a service pointing at
your provider's base URL:
openai → https://api.openai.com/v1
Base URLs must use https:// — plain-http upstreams are rejected.
2. Store your provider key
Paste the provider API key into the service's token vault. It is stored server-side, encrypted at rest, and masked from that moment on — no API or dashboard screen returns the full value again. You can add several keys per service with priorities for failover, and rotate or revoke them without an app release.
3. Get a user token and call the proxy
Your app exchanges its app ID and a user identifier for a short-lived JWT.
Two prerequisites: set APP_ID to your app's UUID (copy it from
the application's page in the dashboard — the example below will 404 as-is), and
jq, used only to extract the token:
APP_ID=550e8400-e29b-41d4-a716-446655440000 # ← replace with your App ID
JWT=$(curl -s -X POST https://api.myapptoken.com/api/v1/auth/simple \
-H 'Content-Type: application/json' \
-d "{\"app_id\": \"$APP_ID\", \"user_id\": \"user-123\"}" | jq -r .access_token)
No jq? Run the curl alone and set
JWT=<access_token from the response> by hand. The full response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs…",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": "2026-08-06T20:00:00Z",
"services": {
"openai": {
"limits": {
"requests": 100, "remaining": 100, "window": "hour",
"disabled": false, "resets-in": 3600
}
}
}
}
disabled and resets-in (seconds) reflect the user's
rate-limit cooldown state — see rate limits.
Then call the provider through the proxy — same paths, same request and response shapes, with the JWT in place of the provider key:
curl https://api.myapptoken.com/api/v1/proxy/$APP_ID/openai/images/generations \
-H "Authorization: Bearer $JWT" \
-H 'Content-Type: application/json' \
-d '{"model": "gpt-image-1", "prompt": "a lighthouse at dusk", "size": "1024x1024"}'
(Image generation is a good first test: responses are buffered today, so non-streaming endpoints show the proxy at its best. Chat completions work the same way — minus token-by-token streaming, which is in development.)
In app code the whole change is the base URL and the credential:
// Swift — before let baseURL = "https://api.openai.com/v1" let apiKey = "sk-proj-…" // shipped with the app // after — <app-id> is your app's UUID from the dashboard let baseURL = "https://api.myapptoken.com/api/v1/proxy/<app-id>/openai" let apiKey = sessionJWT // from /auth/simple, expires in 1 h
Authentication reference
| Endpoint | Description |
|---|---|
POST /api/v1/auth/simple |
Body {"app_id", "user_id"} → JWT valid for 3600 seconds.
The response includes the per-service rate-limit budget for that user. |
POST /api/v1/auth/refresh |
Header Authorization: Bearer <jwt> → fresh JWT with a new
one-hour expiry. |
Threat model, stated plainly: auth/simple takes a
caller-chosen user ID and no other proof. Anyone who discovers your app ID can mint
tokens for fresh user IDs, so per-user rate limits alone are damage control — they
contain accidental overuse and unsophisticated abuse, not a determined attacker. For
production mobile apps, enable Firebase App Check: proxy
calls then additionally require proof they come from a genuine build of your app.
Proxy reference
Every HTTP method is supported. The URL format is:
https://api.myapptoken.com/api/v1/proxy/{app_id}/{service_name}/{provider_path}
app_id is the application's UUID; service_name is the
name you gave the service (e.g. openai).
The proxy validates the JWT, applies the user's rate limit, selects an active provider key (by priority, with failover), forwards the request to the service's base URL with the key injected, and returns the provider's response unchanged.
- Auth injection:
Authorization: Bearer <key>by default — any Bearer-auth API works out of the box. Google Gemini (x-goog-api-key) and fal.ai (Authorization: Key) header schemes are built in. APIs needing HMAC signing or other custom auth schemes are not supported yet. - Binary-safe: request and response bodies pass through untouched, so image, video and audio endpoints work as well as JSON.
- Streaming: responses are currently buffered — ideal for image generation and short completions. Token-by-token streaming (SSE) for chat UIs is in development.
Rate limits
Each service has a per-user request limit over a rolling window, configurable in the dashboard. A user who exceeds it is temporarily disabled for one window and receives:
HTTP 429
{
"error": "rate_limit_exceeded",
"message": "Temporarily disabled: rate limit exceeded",
"limit": 100,
"window": "hour",
"retry_after_seconds": 3540
}
The /auth/simple response carries each service's remaining budget, so
your app can show "N requests left" without extra calls. You can also disable a
specific user for a service permanently, in one click, from the dashboard.
Firebase App Check
Enable App Check per application in the dashboard (with your Firebase project number and app IDs). Once enabled, every proxy call must carry a valid App Check token:
X-Firebase-AppCheck: <token from the App Check SDK>
Calls without a valid token get 401 {"error": "appcheck_failed"}. This
is the mechanism that restricts proxy access to genuine builds of your app.
For strongest protection, enter explicit Firebase App IDs. Leaving the app-ID list empty accepts tokens from any app in that Firebase project — fine for a single-app project, too broad otherwise.
Data handling
- Request and response bodies are logged by default — this powers your statistics and AI Insights. Logs are visible only to your account and exportable as CSV.
- Per-service logging opt-out and configurable retention are on the roadmap; today, logs are retained until your account is deleted or you ask us to delete them.
- Everything runs on AWS us-east-1. Details in the privacy policy.
Beta limits
Up to 5 applications per account, unlimited services and keys. There is no published request cap during beta — we contact heavy users before any restriction. Pricing and limit changes come with at least 30 days' notice; see pricing.
Questions? hello@myapptoken.com