Access Matrix
Every public route with the credential it needs, the plan that unlocks it, the rate bucket it is metered on, and the outcome per plan. Generated from the API route policy.
Generated by pnpm --filter @philidor/api access:matrix -- --mdx from packages/shared/src/route-policy.ts (re-exported as apps/api/src/lib/route-policy.ts), the same table that drives the OpenAPI security declarations and the cache invariant. Do not hand-edit; regenerate.
What each plan gets
| Plan | API key tier | Default rate limit (enforced) | Fair use (not enforced) | Licence | Capabilities |
|---|---|---|---|---|---|
| Free | — | none | — | internal, not redistributable | — |
| Analyst | analyst | 30/min | 25000/month | internal, not redistributable, 1 seat | — |
| Pro | pro | 60/min | 150000/month | internal, not redistributable, 3 seats | — |
| Data | data | 100/min | — | contract, not redistributable | — |
| Decisioning | decisioning | 600/min | — | contract, not redistributable | overhang, risk_graph_signed_decisions, webhooks |
| Embedded | embedded | 10000/min | — | contract, redistributable | overhang, risk_graph_signed_decisions, webhooks |
A key is issued with its plan's default rate limit unless a different limit was agreed (recorded on the key as contracted_rpm); GET /v1/me reports the effective limit. A self-serve key's live rpm is the org plan's, so an upgrade applies without re-minting.
Only the per-minute rate limit is enforced. The Analyst (25000) and Pro (150000) monthly figures are fair-use guides from a conservative peer estimate: no monthly meter exists, so requests past them are not refused. SSE is Decisioning and Embedded only. Pro CSV export is capped at a provisional 100 MB/month (PROVISIONAL_PRO_CSV_EXPORT_CAP_BYTES); Analyst has no bulk or export. History and the other depth families stay closed for self-serve.
Routes
ok means the credential and plan pass the access gate for valid inputs, not a guarantee of success or coverage; 401 means a key is required; 403 means the plan is too low. Outcomes assume paid-tier enforcement is active. Family budgets allow the per-IP fallback when the key budget is exhausted; SSE uses concurrent connection limits. Validation, signatures, rollout configuration, coverage, and rate limiting can still reject a call.
| Method | Path | Plan | Anonymous | Free | Analyst | Pro | Data | Decisioning | Embedded | Rate bucket (anonymous) | Keyed |
|---|---|---|---|---|---|---|---|---|---|---|---|
| GET | /v1/access/families | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/address/:address/positions | — | ok | ok | ok | ok | ok | ok | ok | portfolio (10/60s per IP) | max(key rpm, 10)/min per key; IP fallback |
| GET | /v1/assets | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/:chain_id/:address | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/:symbol/collateral | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/:symbol/history | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/:symbol/peg-history | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/by-network/:caip2/:address/assessment | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/by-network/:caip2/:address/financials | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/enriched | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/enriched/facets | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/assets/machine-scores/:asset_id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/baskets | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id/changes | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id/methodology/versions | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id/version/:versionId | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id/versions | Data | 403 | 403 | 403 | 403 | ok | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/baskets/:id/webhooks | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| POST | /v1/baskets/:id/webhooks | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| DELETE | /v1/baskets/:id/webhooks/:whId | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| POST | /v1/baskets/:id/webhooks/:whId/enable | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| POST | /v1/baskets/:id/webhooks/:whId/replay | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| GET | /v1/baskets/webhooks | Decisioning | 403 | 403 | 403 | 403 | 403 | ok | ok | basketsRead (60/60s per IP) | max(key rpm, 60)/min per key; IP fallback |
| GET | /v1/chains | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/chat | — | ok | ok | ok | ok | ok | ok | ok | userChat (2/60s per IP) | 2/60s per IP |
| GET | /v1/curators | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/curators/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/curators/:id/events | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/docs | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/events | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/events/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/events/group/:groupKey | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/events/stream | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | sse_connections (5 concurrent per IP (before enforcement only)) | 200 concurrent per key; 5 per reported viewer |
| GET | /v1/evidence/signers | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/graph/attestation/:id/verify | — | ok | ok | ok | ok | ok | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/breach | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| POST | /v1/graph/check | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graphCheck (60/60s per IP) | family budget 60/min per key; IP fallback |
| GET | /v1/graph/curator-exposure | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/decision/:id/verify | — | ok | ok | ok | ok | ok | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/expected-dependency-loss | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/expected-dependency-loss/summary | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/incident-exposure | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/incident-exposure/summary | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/look-through | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/graph/snapshot/:id | — | ok | ok | ok | ok | ok | ok | ok | graph (600/60s per IP) | max(key rpm, 600)/min per key; IP fallback |
| GET | /v1/health | — | ok | ok | ok | ok | ok | ok | ok | health (120/60s per IP) | 120/60s per IP |
| GET | /v1/integrations/royco/markets/:slug | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/markets | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/markets/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/markets/:id/events | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/me | — | 401 | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/methodology | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/methodology/vault | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/newsletter/confirm | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/newsletter/subscribe | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/ondo/global-markets | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/ondo/global-markets/:symbol | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/ondo/global-markets/:symbol/data | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/ondo/global-markets/:symbol/stream | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/openapi.json | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/oracle-vector/freshness | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/por | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/por/:issuer | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/por/:issuer/history | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/portfolio/overlap | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/protocols | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/protocols/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/backtests | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/claims | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/model-health | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/predictions | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/sources | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/research/validation-reports | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/reviewers | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/rwa | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/rwa/:asset_id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/rwa/coverage | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/rwa/facets | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/rwa/stats/history | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/security-events | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/security-events/losses | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/signals | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/signals/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/stablecoins/allocators | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/stablecoins/backing | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/stats | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/stats/history | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/stats/rating-dynamics | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/status | — | ok | ok | ok | ok | ok | ok | ok | status (60/60s per IP (local)) | 60/60s per IP (local) |
| GET | /v1/users/:address/agents | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| PUT | /v1/users/:address/agents | — | ok | ok | ok | ok | ok | ok | ok | userWrite (10/60s per IP) | 10/60s per IP |
| GET | /v1/users/:address/agents/auth-message | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/users/:address/terms | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/users/:address/terms | — | ok | ok | ok | ok | ok | ok | ok | userWrite (10/60s per IP) | 10/60s per IP |
| GET | /v1/users/:address/terms/auth-message | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/events | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/holders | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/holders/history | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/markets | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/score-history | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/snapshots | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/strategies | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vault/:network/:address/strategy | Data | 403 | 403 | 403 | 403 | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vaults | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vaults/:id | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/vaults/batch | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vaults/changes | Pro | 403 | 403 | 403 | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vaults/scores | Pro | 403 | 403 | 403 | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/vaults/with-critical-incidents | — | ok | ok | ok | ok | ok | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| GET | /v1/webhooks | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/webhooks | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| DELETE | /v1/webhooks/:id | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| GET | /v1/webhooks/:id | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| PATCH | /v1/webhooks/:id | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| GET | /v1/webhooks/:id/deliveries | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | public (10/60s per IP) | the key rpm (X-RateLimit-Limit) |
| POST | /v1/webhooks/:id/enable | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| POST | /v1/webhooks/:id/replay | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |
| POST | /v1/webhooks/:id/test | Decisioning | 401 | 403 | 403 | 403 | 403 | ok | ok | basketsWebhookWrite (30/60s per IP) | family budget 30/min per key; IP fallback |