Account
Read and manage the authenticated user’s account — profile, balance, billing settings, spend reporting, connected apps, and deletion. All endpoints are scoped to the user behind the session token; there is no admin variant on this surface.
Get account#
Returns the signed-in user’s profile, balance, plan, billing configuration, and any linked third-party provider subscriptions (e.g. ChatGPT via OAuth — see BYOK).
Response
{
"id": "bc9aac4f-...",
"email": "you@example.com",
"balance": 8471500,
"plan": "free",
"created_at": "2026-01-14T18:22:09.114Z",
"name": "Ada Lovelace",
"avatar_url": "https://cdn.example.com/me.png",
"user_metadata": { "company": "Analytical Engines Inc." },
"linked_providers": [
{
"provider": "openai",
"subscription_tier": "plus",
"linked_at": "2026-04-02T11:08:33.510Z",
"status": "active"
}
],
"billing": {
"has_payment_method": true,
"auto_topoff_enabled": false,
"auto_topoff_threshold": 0,
"auto_topoff_amount": 0
}
}Response fields
| iduuid | The user’s Quota ID. |
| emailstring | Login email. Lowercased. |
| balanceinteger | Current credit balance. 1,000,000 credits = $1.00. Can be negative after a streaming overshoot. |
| planstring | Plan slug (e.g. free). |
| created_atISO 8601 | When the account was created. |
| namestring | null | Display name. Nullable until set. |
| avatar_urlstring | null | Profile avatar URL. Nullable until set. |
| user_metadataobject | Free-form JSON the user has attached to their profile. Defaults to {}. |
| linked_providersarray | Provider OAuth links the user has authorized — see BYOK. Each entry has provider, subscription_tier, linked_at, status. |
| billing.has_payment_methodboolean | True once the user has completed a Stripe checkout (any successful purchase saves the customer). |
| billing.auto_topoff_enabledboolean | When true and a saved card is on file, Quota auto-charges when the balance crosses the threshold. |
| billing.auto_topoff_thresholdinteger | Trigger level in credits. When balance falls below this, auto-topoff fires. |
| billing.auto_topoff_amountinteger | Credits to add per auto-topoff event. |
Update profile#
Updates the user’s profile fields. Each field is independently optional. Pass null to clear name or avatar_url; omit a field to leave it untouched.
Body
| namestring | null | New display name, or null to clear. Validated against the same rules as signup. |
| avatar_urlstring | null | HTTPS URL to an avatar image, or null to clear. |
| user_metadataobject | Free-form JSON, fully replacing the prior value. Limited in size by the user-profile validator. |
Request
curl -X PATCH https://api.usequota.ai/account \
-H "Authorization: Bearer sess_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"user_metadata": { "company": "Analytical Engines Inc." }
}'Response
{
"id": "bc9aac4f-...",
"email": "you@example.com",
"name": "Ada Lovelace",
"avatar_url": null,
"user_metadata": { "company": "Analytical Engines Inc." }
}Errors
| 400 invalid_name | name was not a string or null, or failed the profile validator. |
| 400 invalid_avatar_url | avatar_url was not a string or null, or failed the URL validator (must be HTTPS, no localhost). |
| 400 invalid_user_metadata | user_metadata failed validation (size, depth, or non-JSON-safe values). |
| 404 not_found | Session points at a user row that no longer exists. |
Delete account#
Soft-deletes the account. The user row is retained for ledger and OAuth-audit integrity, but PII is anonymized and login is made impossible by any path.
On success the server, in one transaction:
- Sets
deleted_at = NOW()on the user row. - Anonymizes
emailtodeleted-<id>@quota.deletedand nullsname+avatar_url. - Replaces
password_hashwith a fresh bcrypt hash over a random 32-byte string — defence in depth, thedeleted_at IS NULLfilter on login already blocks re-auth. - Revokes every active session and non-revoked OAuth token for the user.
- Sends a confirmation email to the original address (best-effort — a delivery failure does not roll back the deletion).
Body
| passwordstringrequired | The user’s current password, re-confirmed via bcrypt against the stored hash. Required even if the user is mid-session. |
Request
curl -X DELETE https://api.usequota.ai/account \
-H "Authorization: Bearer sess_..." \
-H "Content-Type: application/json" \
-d '{ "password": "your-current-password" }'Response
{
"ok": true,
"message": "Your account has been deleted."
}Errors
| 400 invalid_password | Password missing, empty, or did not match the stored hash. Also returned when the session points at an OAuth-only user with no password set, so the response shape is the same in either case (no enumeration oracle). |
| 401 unauthorized | Missing or expired session token. |
Update settings (auto top-off)#
Updates the user’s auto top-off configuration. Auto top-off, once enabled and with a saved card on file, charges the user’s Stripe customer when their balance falls below auto_topoff_threshold, adding auto_topoff_amount credits per event.
Body
| auto_topoff_enabledboolean | Master switch. When false, the threshold and amount are kept but the trigger is off. |
| auto_topoff_thresholdinteger | Trigger level in credits. Must be >= 0. Balance falling below this fires a top-off. |
| auto_topoff_amountinteger | Credits to add per top-off event. Must be >= 0. |
Request
curl -X PATCH https://api.usequota.ai/account/settings \
-H "Authorization: Bearer sess_..." \
-H "Content-Type: application/json" \
-d '{
"auto_topoff_enabled": true,
"auto_topoff_threshold": 1000000,
"auto_topoff_amount": 5000000
}'Response
{
"auto_topoff_enabled": true,
"auto_topoff_threshold": 1000000,
"auto_topoff_amount": 5000000
}Errors
| 400 invalid_threshold | auto_topoff_threshold was negative. |
| 400 invalid_amount | auto_topoff_amount was negative. |
Get spend time series#
Returns daily credit-usage buckets over the requested window. Buckets are aligned to UTC days; days with no usage are present as zero entries so the series is contiguous.
Query
| period"7d" | "30d" | "90d" | Window length. Defaults to "30d". |
Request
curl https://api.usequota.ai/account/spend?period=7d \
-H "Authorization: Bearer sess_..."Response
{
"period": "7d",
"total_credits_used": 142500,
"data": [
{ "date": "2026-05-03", "credits_used": 0 },
{ "date": "2026-05-04", "credits_used": 28100 },
{ "date": "2026-05-05", "credits_used": 0 },
{ "date": "2026-05-06", "credits_used": 51200 },
{ "date": "2026-05-07", "credits_used": 0 },
{ "date": "2026-05-08", "credits_used": 63200 },
{ "date": "2026-05-09", "credits_used": 0 }
]
}Errors
| 400 invalid_period | period was not one of "7d", "30d", "90d". |
Get connected apps#
Returns the list of apps the user has authorized through Sign in with Quota, with each app’s 30-day credit spend and the timestamp of its most recent request. Useful for an end-user “Apps connected to your account” dashboard.
Response
{
"apps": [
{
"app_id": "9f3a2b1c-...",
"name": "Acme Writer",
"credits_used": 612400,
"last_used_at": "2026-05-08T19:14:02.000Z"
},
{
"app_id": "5d2e8a01-...",
"name": "QuokkaChat",
"credits_used": 81000,
"last_used_at": "2026-04-21T07:33:18.000Z"
}
]
}Window is fixed at 30 days. Apps with zero usage in the window are omitted.
Create billing checkout#
Creates a Stripe Checkout session for the chosen credit package and returns the URL to redirect the user to. Quota uses the request Origin header (validated against ALLOWED_ORIGINS) to build the success and cancel URLs.
Body
| package_idstringrequired | One of the canonical package IDs: starter, basic, plus, pro. Each maps to a credit count and USD price; call GET /v1/packages for the full table. |
Request
curl -X POST https://api.usequota.ai/account/billing/checkout \
-H "Authorization: Bearer sess_..." \
-H "Origin: https://your-app.example.com" \
-H "Content-Type: application/json" \
-d '{ "package_id": "starter" }'Response
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_test_...",
"session_id": "cs_test_..."
}Errors
| 400 invalid_package | package_id missing or not one of the supported values. |
| 502 stripe_error | Stripe rejected the create-session request. The original error is logged server-side. |
Account dashboard (HTML)#
Returns a self-contained HTML page that wires together every endpoint on this page — balance, spend chart, connected apps, provider links, and billing settings — using only the session cookie. Intended as a fallback admin surface for users who don’t have a dashboard built into the developer’s app.
The page calls the same endpoints documented above. There is no machine-readable variant.