REST API Reference
Current route-family map for Bridge, Fixie, Solana, data, documents, and platform endpoints.
The REST surface in apps/api is broad, but it is no longer documented here as a single random list. This page groups the route families that exist in the current codebase and flags which ones are public-facing versus internal.
Base URL: https://api.fxyz.network/api
GraphQL remains the canonical application API. REST is best for service contracts, uploads, streams, third-party integrations, and operational surfaces.
Authentication
Most protected routes use:
Authorization: Bearer <privy-jwt-token>
x-persona-id: <persona-id>Some operational or webhook routes use secrets or service-specific verification instead of user JWTs.
Public Route Families
Bridge
/api/bridge/kyc-links
/api/bridge/virtual-accounts
/api/bridge/external-accounts
/api/bridge/transfers
/api/bridge/transfers/[transferId]
/api/bridge/liquidation
/api/bridge/liquidations
/api/bridge/rates
/api/bridge/customers/[customerId]/capabilities
/api/bridge/customers/[customerId]/kyc-linkUse these routes for KYC, linked bank accounts, pay-ins, off-ramps, and quote/rate flows.
Fixie
/api/fixie
/api/fixie/[agentId]
/api/fixie/[agentId]/chat
/api/fixie/[agentId]/stream
/api/fixie/[agentId]/memory
/api/fixie/[agentId]/blocks
/api/fixie/[agentId]/tools
/api/fixie/templates
/api/fixie/tools
/api/fixie/tools/neo4j-queryThese routes cover agent lifecycle, chat, streaming, memory blocks, and tool execution.
Telegram
/api/telegram/webhook
/api/telegram/setup
/api/telegram/userThese routes handle the Telegram bot webhook (receives messages, routes to Letta), webhook registration with the Telegram Bot API, and Telegram user-to-agent mapping in Neo4j. The Telegram mini app at /telegram-app uses the standard /api/fixie/{agentId}/stream endpoint.
Solana
/api/solana/balance
/api/solana/assets
/api/solana/portfolio
/api/solana/rpc
/api/solana/token-account
/api/solana/transactions
/api/solana/nft-metadataUse these routes for wallet balances, portfolio views, asset inventory, transaction history, and selected RPC passthroughs.
Data And Market Surfaces
/api/prices
/api/prices/[asset]
/api/fx/rates
/api/fx/bis
/api/market-data
/api/cbdc
/api/neo4j/stats
/api/healthThese routes expose price, FX, market, CBDC, graph stats, and health information.
Documents
/api/documents
/api/documents/[id]
/api/documents/uploadThese support document inventory and upload flows. seed-bibliography exists in the repo but is operational rather than end-user facing.
Platform Flows
/api/allocate
/api/allocate/request
/api/allocate/graph
/api/membership/proof/[did]
/api/membership/proof/internal/[did]
/api/membership/[mint]/metadata
/api/stars
/api/stars/available
/api/stars/[starId]
/api/stars/[starId]/metadata
/api/stars/mint-nft
/api/notifications
/api/whoamiThese routes cover allocation workflows, proofs, stars, notifications, and session/user inspection.
Legacy
/api/invest/*is 308-redirected to/api/allocate/*for one release after the MiCA rename. The redirect will be removed in a subsequent deploy : update any bookmarked clients before then.
Internal Or Operational Routes
The following route families exist, but they are not public integration entry points:
/api/admin/*/api/cron/*/api/governance/seed/api/documents/seed-bibliography- webhook handlers under
apps/api/app/webhooks/*
Choosing REST vs GraphQL
- Use REST when the action is tightly bound to a service boundary or transport pattern.
- Use GraphQL when you want typed application models or multi-resource queries.
Public data API (apps/web)
Everything above documents apps/api. apps/web — the public marketing/network site — also ships its own route handlers under apps/web/app/api/. They are a separate, smaller surface and are not covered elsewhere in these docs.
None of these routes use the Privy-JWT model from the Authentication section above.
Each route's auth posture is stated explicitly per-row below — do not assume it inherits
the apps/api framing.
| Path | Method | Auth | Purpose |
|---|---|---|---|
/api/token/[token] | GET | Public — no auth check in the route handler | Resolves static token metadata (florin / joule / how / fxyz) from an in-repo table (app/lib/token-metadata.ts); no live Neo4j call, no pricing/valuation data. |
/api/ontology/[concept] | GET | Public — no auth check in the route handler | Resolves an ontology concept (class/property) via fetchOntologyConceptDetails, which reads Neo4j through the public GraphQL surface. |
/api/currency/[ticker] | GET | Public — no auth check in the route handler | Resolves a stablecoin or CBDC record by ticker/uid from the site's own stablecoin/CBDC data libraries (getStablecoinData(), getCBDCData()). |
/api/substrate/landing | GET | Public — no auth check in the route handler | Returns the LandingSpec JSON for the landing surface (synthetic-anonymous / publicSurfaceEligible slice only, per the route's own comment). Calls renderLanding() from @repo/substrate-adapters against Neo4j; 500 if NEO4J_URI/NEO4J_USER/NEO4J_PASSWORD are unset. |
/api/substrate/atlas | GET | Public — no auth check in the route handler | Returns the AtlasSpec JSON (institutional entities — FinancialInstitution / RegulatoryBody / CBDCProgram / PaymentSystem), optionally filtered by a realm query param (physical/electronic/digital). Same Neo4j-env-required behavior as substrate/landing. |
/api/substrate/cartography | GET | Gated — requires header x-fxyz-internal to equal the server-side INTERNAL_REQUEST_SECRET env var; fails closed (403) if the secret is unset or doesn't match | Returns the CartographySpec JSON: a 4-hop member ego-graph rooted at a required rootMemberDid query param. The route's own comment states this is member-to-member data, not public-surface data, and is intended for trusted server-to-server callers only — not browsers. |
/api/substrate/deck | GET | Public — no auth check in the route handler | Returns the DeckSpec JSON (deck spine resolved against live graph state). Same Neo4j-env-required behavior as substrate/landing. |
/api/graph/ego | GET | Public — no auth check in the route handler | Same-origin proxy to the apps/api entity-ego endpoint. Validates a required ref query param against the GraphRef grammar (isGraphRef from @repo/graph-contract) before forwarding; 400 if missing/invalid, 502 on upstream failure. |
/api/graph/market | GET | Public — no auth check in the route handler | Same-origin proxy to the apps/api market-payload endpoint. Passes through a tier query param (tile if exactly "tile", else panel); 502 on upstream failure. |
Auth model
substrate/cartography is the single exception on this surface: it is gated behind a first-party trust header rather than a user credential, and denies (403) any request that doesn't carry it — including ordinary browser requests. Every other route listed above has no authentication or authorization check at all in its handler; access control, where it exists, happens further upstream (e.g. what fetchOntologyConceptDetails or the apps/api origin choose to expose on the "public" slice they return) rather than in the apps/web handler itself. See each route handler for the exact upstream call.
Linked-Data content negotiation (token, ontology, currency)
token/[token], ontology/[concept], and currency/[ticker] are the one family here: each resolves an entity and can serve it as a dereferenceable Linked-Data resource, driven by a ?format= query param first and the Accept header second. Verified against each handler directly — their behavior is not identical:
token/[token]is the only one of the three with a dedicated JSON branch:format=jsonorAccept: application/json→ JSON body (includes an@idfield), checked before the HTML-redirect branch.- All three redirect (
303) to a localized HTML page when there is noformatparam andAccepteither includestext/htmlor simply doesn't includetext/turtle/application/rdf+xml. Because of that second clause, a bareAccept: application/jsonwith noformatparam is redirected to HTML onontologyandcurrency(they have no JSON branch to catch it first) — onlytokenspecial-cases JSON ahead of the redirect check. - All three support
format=ttl(orAccept: text/turtle/application/x-turtle) →text/turtle, andformat=xml(orAccept: application/rdf+xml) →application/rdf+xml. Anything that reaches neither branch →406 Not Acceptable. - Locale for the HTML redirect is resolved from
Accept-Language(pl/de/esprefix match, elseen) identically in all three handlers. - Turtle/RDF-XML responses on all three set
Cache-Control: public, max-age=86400andVary: Accept. - Not-found behavior differs:
tokenandcurrencyreturn a plain-text404("Token Not Found"/"Currency Not Found");ontologyreturns a404with a JSON body ({ "error": "Ontology concept not found in graph" }).
Related docs: