This document describes the public Edge Function endpoints used by the VibeUsage tracker (CLI) and dashboard.
- Author source code lives in
insforge-src/. - Deployable artifacts live in
insforge-functions/and are generated (single-file). - Do not hand-edit
insforge-functions/*.js; editinsforge-src/and rebuild.
Build deploy artifacts:
npm run build:insforgeVerify artifacts are up to date (no writes):
npm run build:insforge:checkDeploy (example):
# Update code only; keep existing slugs.
insforge2 update-function --slug vibeusage-usage-summary --codeFile insforge-functions/vibeusage-usage-summary.js- User JWT endpoints:
Authorization: Bearer <user_jwt>- Used by dashboard and user settings.
- Device token endpoints:
Authorization: Bearer <device_token>- Used by CLI ingestion; long-lived; server stores only sha256 hash.
Local user JWT verification uses INSFORGE_JWT_SECRET (HS256) in the Edge Functions environment. It must match the JWT signing secret.
All endpoints support CORS OPTIONS preflight.
- Public edge functions are served at
/functions/<slug>(CORS enabled). - Admin API path
/api/functions/<slug>requires a project admin API key and is not suitable for browser clients. - Dashboard uses
/functionsand only falls back to/api/functionson 404 in privileged contexts.
When ingestion hangs or fails, use these client-side controls:
VIBEUSAGE_HTTP_TIMEOUT_MS: HTTP request timeout in milliseconds.0disables timeouts. Default20000. Clamped to1000..120000.VIBEUSAGE_DEBUG=1or--debug: print request/response timing and original backend errors to stderr.
Examples:
VIBEUSAGE_HTTP_TIMEOUT_MS=60000 npx --yes vibeusage sync --debugPricing metadata is resolved from vibeusage_pricing_profiles. The default pricing profile is selected by:
VIBEUSAGE_PRICING_SOURCE(defaultopenrouter)VIBEUSAGE_PRICING_MODEL(defaultgpt-5.2-codex; exact match or*/<model>suffix match)
OpenRouter sync requires these environment variables in InsForge:
OPENROUTER_API_KEY(required)OPENROUTER_HTTP_REFERER(optional, for attribution)OPENROUTER_APP_TITLE(optional, for attribution)
Health check:
- See
docs/ops/pricing-sync-health.mdandscripts/ops/pricing-sync-health.sql.
Alias mapping:
vibeusage_pricing_model_aliasesmapsusage_model->pricing_modelwitheffective_from.- Resolver checks alias mapping before suffix matching.
- Prefixed usage models require explicit aliases; without one, pricing falls back to the default profile (no suffix inference).
To reduce runaway scans and runtime resets, usage read endpoints enforce bounded ranges and emit slow-query logs.
VIBEUSAGE_USAGE_MAX_DAYS: max day span forGET /functions/vibeusage-usage-summary,.../vibeusage-usage-daily, and.../vibeusage-usage-model-breakdown. Default800. Oversized ranges return400withDate range too large (max N days).VIBEUSAGE_SLOW_QUERY_MS: slow-query log threshold in milliseconds. Default2000. When exceeded, astage: slow_querylog is emitted withquery_label,duration_ms, androw_count.
To keep low-tier backends stable, the CLI and dashboard apply conservative defaults:
- CLI auto sync interval: ~10 minutes (with jitter)
- CLI batch size: 300 (max batches per auto run: 2 small / 4 large)
- Dashboard backend probe: every 60 seconds, paused when the tab is hidden
Timezone note: Usage endpoints accept tz (IANA) or tz_offset_minutes (fixed offset). When provided and non-UTC, date boundaries are interpreted in that timezone. When omitted, usage endpoints default to UTC behavior.
Canary note: Usage endpoints exclude source=model=canary buckets by default unless explicitly requested via source=canary or model=canary.
Issue a long-lived device token for the current user.
Auth:
- User mode:
Authorization: Bearer <user_jwt> - Admin bootstrap (optional):
Authorization: Bearer <service_role_key>withuser_idin body
Request body:
{ "device_name": "my-mac", "platform": "macos" }Response:
{ "device_id": "uuid", "token": "opaque", "created_at": "iso" }Issue a short-lived, single-use link code bound to the current user session.
Auth:
Authorization: Bearer <user_jwt>
Request body:
{}Response:
{ "link_code": "string", "expires_at": "iso" }Notes:
- Link codes expire after ~10 minutes.
- Each link code can be used once.
Exchange a link code for a device token (CLI init flow).
Auth:
- None (public function; server uses service role internally)
Request body:
{
"link_code": "string",
"request_id": "string",
"device_name": "string?",
"platform": "string?"
}Response:
{ "token": "opaque", "device_id": "uuid", "user_id": "uuid" }Notes:
request_idis required for replay safety; retries with the samerequest_idreturn the same token.- Expired link codes return
400and used codes return409.
Return privacy-safe profile fields for a public share token.
Auth:
Authorization: Bearer <share_token>
Response:
{ "display_name": "string|null", "avatar_url": "string|null" }Notes:
display_nameis derived from user metadata and sanitized; email-like values are removed.avatar_urlis returned only forhttp/httpsURLs with length ≤ 1024; otherwisenull.
Ingest half-hour token usage aggregates from a device token idempotently.
Auth:
Authorization: Bearer <device_token>
Request body:
{
"hourly": [
{
"hour_start": "2025-12-23T06:00:00.000Z",
"source": "codex",
"model": "unknown",
"input_tokens": 0,
"cached_input_tokens": 0,
"output_tokens": 0,
"reasoning_output_tokens": 0,
"total_tokens": 0
}
],
"device_subscriptions": [
{
"tool": "codex",
"provider": "openai",
"product": "chatgpt",
"planType": "pro"
},
{
"tool": "claude",
"provider": "anthropic",
"product": "subscription",
"planType": "max",
"rateLimitTier": "default_claude_max_5x"
}
]
}Response:
{
"success": true,
"inserted": 123,
"skipped": 0,
"project_inserted": 0,
"project_skipped": 0
}Notes:
hour_startmust be a UTC half-hour boundary ISO timestamp (:00or:30).sourceis optional; when missing or empty, it defaults tocodex.modelis optional; when missing or empty, it defaults tounknown.- Uploads are upserts keyed by
user_id + device_id + source + model + hour_start. device_subscriptionsis optional and stores latest tool subscription markers (user_id + tool + provider + productupsert).- Backward compatibility:
{ "data": { "hourly": [...] } }is accepted, but{ "hourly": [...] }remains canonical. hour_startis the usage-time bucket. Databasecreated_at/updated_atreflect ingest/upsert time, so many rows can share the same timestamp when a batch is uploaded.- Internal observability: ingest requests also write a best-effort metrics row to
vibeusage_tracker_ingest_batches(project_admin only). Fields includebucket_count,inserted,skipped,source,user_id,device_id, andcreated_at. No prompt/response content is stored. - Retention:
POST /functions/vibeusage-events-retentionsupportsinclude_ingest_batchesto purge ingest batch metrics older than the cutoff. - When concurrency limits are exceeded, the endpoint may return
429withRetry-Afterto signal backoff. The guard is opt-in viaVIBEUSAGE_INGEST_MAX_INFLIGHT.
Record a throttled sync heartbeat for a device token. Used to distinguish “unsynced” from “no usage”.
Auth:
Authorization: Bearer <device_token>
Response:
{
"success": true,
"updated": true,
"last_sync_at": "2025-12-22T12:30:00Z",
"min_interval_minutes": 30
}Return Pro status for the authenticated user.
Auth:
Authorization: Bearer <user_jwt>
Response:
{
"user_id": "uuid",
"created_at": "iso|null",
"pro": {
"active": true,
"sources": ["registration_cutoff", "entitlement"],
"expires_at": "iso",
"partial": false,
"as_of": "iso"
},
"subscriptions": {
"partial": false,
"as_of": "iso",
"items": [
{
"tool": "codex",
"provider": "openai",
"product": "chatgpt",
"plan_type": "pro",
"rate_limit_tier": null,
"active_start": null,
"active_until": null,
"last_checked": null,
"observed_at": "iso|null",
"updated_at": "iso|null"
}
]
}
}Notes:
- Registration cutoff is fixed at
2025-12-31T23:59:59Asia/Shanghai (2025-12-31T15:59:59Z). - Registration-based Pro expires at
created_at + 99 years. - Entitlements are active when
now_utcis in[effective_from, effective_to)andrevoked_at IS NULL. - When
created_atis unavailable and no service-role key is configured, the endpoint returns a partial result (created_at: null,pro.partial: true) computed from entitlements only. subscriptions.partialmay betruewhen the subscription table has not been migrated yet; in that caseitemsfalls back to an empty list.
Grant an entitlement for a user (admin only).
Auth:
Authorization: Bearer <service_role_key>or aproject_adminJWT
Request body:
{
"id": "uuid?",
"idempotency_key": "string?",
"user_id": "uuid",
"source": "paid|override|manual",
"effective_from": "iso",
"effective_to": "iso",
"note": "string?"
}Response:
{
"id": "uuid",
"user_id": "uuid",
"source": "manual",
"effective_from": "iso",
"effective_to": "iso",
"revoked_at": null,
"note": "string?",
"created_at": "iso",
"updated_at": "iso"
}Notes:
- For idempotent retries, send a stable
idoridempotency_key(the backend derives a deterministic id). - If the
idoridempotency_keyalready exists with a different payload, the endpoint returns409.
Revoke an entitlement by id (admin only).
Auth:
Authorization: Bearer <service_role_key>or aproject_adminJWT
Request body:
{ "id": "uuid", "revoked_at": "iso?" }Response:
{ "id": "uuid", "revoked_at": "iso" }Return token usage totals for the authenticated user over a date range in the requested timezone (default UTC).
Auth:
Authorization: Bearer <user_jwt>
Query:
from=YYYY-MM-DD(optional; default last 30 days)to=YYYY-MM-DD(optional; default today in requested timezone)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)model=<model-id>(optional; filter by model; omit to aggregate all models)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)debug=1(optional; include debug payload for query timing)
Response (bigints as strings):
{
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"days": 30,
"model_id": "gpt-5.2-codex",
"model": "gpt-5.2-codex",
"totals": {
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0",
"total_cost_usd": "0.000000"
},
"pricing": {
"model": "gpt-5.2-codex",
"pricing_mode": "overlap",
"source": "openrouter",
"effective_from": "2025-12-23",
"rates_per_million_usd": {
"input": "1.750000",
"cached_input": "0.175000",
"output": "14.000000",
"reasoning_output": "14.000000"
}
}
}Notes:
- Pricing metadata is resolved from
vibeusage_pricing_profilesusing the configured default model/source and the latesteffective_fromnot in the future (active=true). - If no pricing rows exist, the endpoint falls back to the built-in default profile.
pricing_modeisadd,overlap, ormixed(multiple pricing modes across sources).modelquery uses canonical model id; the backend expands it only to explicit active aliases for the date range (no implicit suffix matching).model_id/modelarenullwhen no model filter is supplied.- When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return top project usage totals for the authenticated user across all recorded history.
Auth:
Authorization: Bearer <user_jwt>
Query:
source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)limit=1..10(optional; default 3)debug=1(optional; include debug payload for query timing)from,to,tz,tz_offset_minutesare accepted for compatibility but ignored (all-time totals only).
Response (bigints as strings):
{
"from": null,
"to": null,
"all_time": true,
"generated_at": "iso",
"entries": [
{
"project_key": "owner/repo",
"project_ref": "https://github.com/owner/repo",
"total_tokens": "0",
"billable_total_tokens": "0"
}
]
}Notes:
- Results are sorted by
billable_total_tokensdescending. - When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return per-source and per-model aggregates for a date range. This endpoint is intended for model mix and cost breakdown UI.
Auth:
Authorization: Bearer <user_jwt>
Query:
from=YYYY-MM-DD(optional; default last 30 days)to=YYYY-MM-DD(optional; default today in requested timezone)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)debug=1(optional; include debug payload for query timing)
Notes:
modelis not accepted because this endpoint already returns per-model groups.- Model groups are aggregated by canonical
model_idacross sources;modelis the display name. - Pricing metadata is resolved from
vibeusage_pricing_profiles. If the range contains exactly one non-unknownmodel, pricing is resolved for that model; otherwise it falls back to the configured default profile. pricing_modeisadd,overlap, ormixed(multiple pricing modes across sources).- When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Response (bigints as strings):
{
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"days": 30,
"sources": [
{
"source": "codex",
"totals": {
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0",
"total_cost_usd": "0.000000"
},
"models": [
{
"model_id": "gpt-5.2-codex",
"model": "gpt-5.2-codex",
"totals": {
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0",
"total_cost_usd": "0.000000"
}
}
]
}
],
"pricing": {
"model": "gpt-5.2-codex",
"pricing_mode": "overlap",
"source": "openrouter",
"effective_from": "2025-12-23",
"rates_per_million_usd": {
"input": "1.750000",
"cached_input": "0.175000",
"output": "14.000000",
"reasoning_output": "14.000000"
}
}
}Return daily aggregates for the authenticated user in the requested timezone (default UTC).
Auth:
Authorization: Bearer <user_jwt>
Query:
from=YYYY-MM-DD(optional; default last 30 days)to=YYYY-MM-DD(optional; default today in requested timezone)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)model=<model-id>(optional; filter by model; omit to aggregate all models)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)
Response:
{
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"model_id": "gpt-5.2-codex",
"model": "gpt-5.2-codex",
"data": [
{
"day": "YYYY-MM-DD",
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0"
}
],
"summary": {
"totals": {
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0",
"total_cost_usd": "0.000000"
},
"pricing": {
"model": "gpt-5.2-codex",
"pricing_mode": "overlap",
"source": "openrouter",
"effective_from": "2025-12-23",
"rates_per_million_usd": {
"input": "1.750000",
"cached_input": "0.175000",
"output": "14.000000",
"reasoning_output": "14.000000"
}
}
}
}Notes:
modelquery uses canonical model id; the backend expands it only to explicit active aliases for the date range (no implicit suffix matching).model_id/modelarenullwhen no model filter is supplied.- The response includes backend-computed
summarytotals; the dashboard MUST NOT compute totals locally. - When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return half-hour aggregates (48 buckets) for the authenticated user on a given local day (timezone-aware; default UTC).
Auth:
Authorization: Bearer <user_jwt>
Query:
day=YYYY-MM-DD(optional; default today in requested timezone)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)model=<model-id>(optional; filter by model; omit to aggregate all models)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)debug=1(optional; include debug payload for query timing)
Response:
{
"day": "YYYY-MM-DD",
"data": [
{
"hour": "YYYY-MM-DDTHH:00:00",
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0",
"missing": true
}
],
"sync": {
"last_sync_at": "2025-12-22T12:30:00Z",
"min_interval_minutes": 30
}
}Notes:
modelquery uses canonical model id; the backend expands it only to explicit active aliases for the date range (no implicit suffix matching).- When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return monthly aggregates for the authenticated user aligned to local months (timezone-aware; default UTC).
Auth:
Authorization: Bearer <user_jwt>
Query:
months=1..24(optional; default24)to=YYYY-MM-DD(optional; default today in requested timezone)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)model=<model-id>(optional; filter by model; omit to aggregate all models)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)debug=1(optional; include debug payload for query timing)
Response:
{
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"months": 24,
"data": [
{
"month": "YYYY-MM",
"total_tokens": "0",
"input_tokens": "0",
"cached_input_tokens": "0",
"output_tokens": "0",
"reasoning_output_tokens": "0"
}
]
}Notes:
modelquery uses canonical model id; the backend expands it only to explicit active aliases for the date range (no implicit suffix matching).- When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return a GitHub-inspired activity heatmap derived from local daily totals (timezone-aware; default UTC).
Auth:
Authorization: Bearer <user_jwt>
Query:
weeks=1..104(optional; default52)to=YYYY-MM-DD(optional; default today in requested timezone)week_starts_on=sun|mon(optional; defaultsun)source=codex|every-code|...(optional; filter by source; omit to aggregate all sources)model=<model-id>(optional; filter by model; omit to aggregate all models)tz=IANA(optional; e.g.America/Los_Angeles)tz_offset_minutes(optional; fixed offset minutes from UTC to local, e.g.-480)debug=1(optional; include debug payload for query timing)
Response:
{
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"week_starts_on": "sun",
"thresholds": { "t1": "0", "t2": "0", "t3": "0" },
"active_days": 0,
"streak_days": 0,
"weeks": [[{ "day": "YYYY-MM-DD", "value": "0", "level": 0 }, null]]
}Notes:
weeksis a list of week columns; each day cell is{ day, value, level }ornullpast the end date.valueis a bigint-as-string.modelquery uses canonical model id; the backend expands it only to explicit active aliases for the date range (no implicit suffix matching).- When
debug=1is set, the response includes adebugobject withrequest_id,status,query_ms,slow_threshold_ms,slow_query.
Return token usage leaderboard for the current UTC period window.
Auth:
- Optional
Authorization: Bearer <user_jwt> - Anonymous requests are supported and return public rows only (
me=null)
Query:
period=week|month|total(required)metric=all|gpt|claude|other(optional; defaultall)limit=1..100(optional; default20)offset=0..10000(optional; default0)
Rules:
period=week: UTC calendar week; week starts Sunday (UTC).period=month: UTC calendar month (1st..last day).period=total: all-time (represented asfrom=1970-01-01andto=9999-12-31).metric=allranks bytotal_tokenswheretotal_tokens = gpt_tokens + claude_tokens + other_tokens.metric=gptranks bygpt_tokens(users withgpt_tokens=0are excluded fromentries;me.rankisnullwhengpt_tokens=0).metric=clauderanks byclaude_tokens(users withclaude_tokens=0are excluded fromentries;me.rankisnullwhenclaude_tokens=0).metric=otherranks byother_tokens(users withother_tokens=0are excluded fromentries;me.rankisnullwhenother_tokens=0).- Leaderboard source scope includes all sources except
source=canary(no source whitelist). - Unknown/unclassified models are included in the
other_tokensbucket. - Privacy-safe: no email and no raw logs.
entries[].is_publicis always a boolean.- Public gating uses canonical
vibeusage_public_viewsactive state (revoked_at IS NULL) at read time. entries[].user_idis exposed only whenis_public=true; otherwise it isnull.- When authenticated, response includes
me(even when not in Top N). - When anonymous,
meisnull.
Response:
{
"period": "week",
"metric": "all",
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"generated_at": "iso",
"page": 1,
"limit": 20,
"offset": 0,
"total_entries": 0,
"total_pages": 0,
"entries": [
{
"user_id": null,
"rank": 1,
"is_me": false,
"is_public": false,
"display_name": "Anonymous",
"avatar_url": null,
"gpt_tokens": "0",
"claude_tokens": "0",
"other_tokens": "0",
"total_tokens": "0"
}
],
"me": {
"rank": null,
"gpt_tokens": "0",
"claude_tokens": "0",
"other_tokens": "0",
"total_tokens": "0"
}
}Return a single leaderboard snapshot entry for a requested user_id and period.
Auth:
- Optional
Authorization: Bearer <user_jwt> - Anonymous access is allowed for public profiles
Query:
user_id=<uuid>(required)period=week|month|total(optional, defaultweek)
Rules:
- Self access (authenticated and
user_id === me) is always allowed. - Non-self access requires active canonical public visibility (
vibeusage_public_views.revoked_at IS NULL). - Snapshot
is_publicis not used as authorization truth.
Response:
{
"period": "week",
"from": "YYYY-MM-DD",
"to": "YYYY-MM-DD",
"generated_at": "iso",
"entry": {
"user_id": "uuid",
"display_name": "string",
"avatar_url": "string|null",
"rank": 1,
"gpt_tokens": "0",
"claude_tokens": "0",
"other_tokens": "0",
"total_tokens": "0"
}
}Read effective public visibility state for current user.
Auth:
Authorization: Bearer <user_jwt>
Response:
{ "enabled": true, "updated_at": "iso", "share_token": "pv1-<uuid>" }Notes:
enabledis canonical state fromvibeusage_public_viewsactive row (revoked_at IS NULL).share_tokenis present only whenenabled=true.
Toggle effective public visibility for current user.
Auth:
Authorization: Bearer <user_jwt>
Request body:
{ "enabled": true }Response:
{ "enabled": true, "updated_at": "iso", "share_token": "pv1-<uuid>" }Notes:
enabled=true: upsert/activate public row (revoked_at=null).enabled=false: revoke public row (revoked_at=now).- Hard-cut semantics: ON => visible immediately; OFF => hidden immediately.
Rebuild leaderboard snapshots for the current UTC period window. Intended for automation (service role only).
Auth:
Authorization: Bearer <service_role_key>
Query (optional):
period=week|month|total(when omitted, refreshesweek+month)
Response:
{
"success": true,
"generated_at": "iso",
"results": [{ "period": "week", "from": "YYYY-MM-DD", "to": "YYYY-MM-DD", "inserted": 42 }]
}Manual refresh runbook:
BASE_URL="https://srctyff5.us-east.insforge.app"
ADMIN_TOKEN="<service_role_key>"
curl -s -X POST "$BASE_URL/functions/vibeusage-leaderboard-refresh?period=week" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
--data "{}"
curl -s -X POST "$BASE_URL/functions/vibeusage-leaderboard-refresh?period=month" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
--data "{}"
curl -s -X POST "$BASE_URL/functions/vibeusage-leaderboard-refresh?period=total" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
--data "{}"Verification:
curl -s "$BASE_URL/functions/vibeusage-leaderboard?period=week" \
-H "Authorization: Bearer <user_jwt>"The following endpoints are retired and return 410 Gone with { "error": "Endpoint retired" }:
POST /functions/vibeusage-leaderboard-settingsGET /functions/vibeusage-public-view-statusPOST /functions/vibeusage-public-view-issuePOST /functions/vibeusage-public-view-revoke
Use GET/POST /functions/vibeusage-public-visibility instead.
Sync OpenRouter Models API pricing into vibeusage_pricing_profiles (admin only).
Auth:
Authorization: Bearer <service_role_key>
Request body:
{ "retention_days": 90, "effective_from": "2025-12-25", "allow_models": ["gpt-5.2-codex"] }Notes:
retention_daysis optional; when provided, rows older than the cutoff are soft-deactivated (active=false).effective_fromdefaults to today (UTC).allow_modelsis optional; when omitted, all models from OpenRouter are processed.- Alias generation: unmatched usage models are mapped via vendor rules (
claude-*->anthropic/*,gpt-*->openai/*) and frozen byeffective_from.
Response:
{
"success": true,
"source": "openrouter",
"effective_from": "2025-12-25",
"models_total": 300,
"models_processed": 280,
"models_skipped": 20,
"rows_upserted": 280,
"usage_models_total": 42,
"aliases_generated": 5,
"aliases_upserted": 5,
"retention": { "retention_days": 90, "cutoff_date": "2025-09-26" }
}Purge legacy tracker events older than a cutoff (admin only).
Auth:
Authorization: Bearer <service_role_key>
Request body:
{ "days": 30, "dry_run": false }Response:
{ "ok": true, "dry_run": false, "days": 30, "cutoff": "iso", "deleted": 123 }Diagnostic endpoint that reports whether the function runtime has the anon key configured and whether the supplied bearer token validates. This does not expose any secrets.
Auth:
- Optional
Authorization: Bearer <user_jwt>to validate the token.
Response:
{
"hasAnonKey": true,
"hasBearer": true,
"authOk": true,
"userId": "uuid",
"error": null
}