Appearance
API
Seven gRPC services in flint.spot.v1. MarketDataService, StatsService, HistoricalService, NodeService, and AuthService are public. MakerService and TxService require credentials.
| Service | Auth | What you use it for |
|---|---|---|
AuthService | none | Mint or revoke bearer session tokens. |
MarketDataService | none | Stream books, fills, market snapshots; list pairs; snapshot a single book. |
StatsService | none | Public aggregate stats — summary, volume breakdown/series, asset TVLs. |
HistoricalService | none | ClickHouse-backed historical fills + candles. |
NodeService | none | Inspect node build/proto identity, health, region, and published endpoints. |
MakerService | bearer session or org API key | Per-maker balances, fills, market snapshots, volume, and activity stats. |
TxService | keypair bearer session | Submit signed transactions, stream blockhash + tx status. |
Compatibility notes
NodeService is available on servers built with the current proto; older deployments return gRPC UNIMPLEMENTED for its RPCs.
The LatLng type kept the same fully-qualified name (flint.spot.v1.LatLng) but moved from maker_admin/messages.proto to common.proto. Wire compatibility is unchanged, but generated source imports move with it: use common_pb2.LatLng in Python and common_pb.ts in TypeScript rather than the former maker-admin module path.
Each is fully wire-compatible with vanilla gRPC and gRPC-Web on the same URL. Pick whichever transport fits your stack — the SDKs hide the difference.
Schema
api.proto— bundled protobuf source covering every service in the package. Use the checked-inproto/tree when you want a per-service slice.openapi.yaml— OpenAPI 3.1 schema for the same service URLs used by gRPC-Web clients, suitable for Postman, Insomnia, Stoplight, or client-generation tools.codama.json— Codama IDL for the on-chainflintprogram, for generating Solana clients (@codama/*, Kinobi) that build the transactionsTxServicesubmits.
CI fails the build if these files diverge from the upstream proto (or, for the IDL, from the on-chain program repo).
URL convention
POST https://<host>/flint.spot.v1.<Service>/<Method>
Content-Type: application/grpc (gRPC binary, hot path)
application/grpc-web+proto (browser-native)No URL params, no path-based versioning beyond the package name.
Authentication
MarketDataService, StatsService, HistoricalService, NodeService, and AuthService are open. MakerService and TxService expect:
authorization: Bearer <session_token>Mint a keypair token via AuthService.Challenge → sign → Authenticate. MakerService also accepts passwordless organization sessions and organization API keys. See the Auth flow recipe for the per-SDK helpers.
Rate limits
Every RPC passes through a per-key token-bucket limiter. The key is your maker identity on authenticated calls — the server resolves your bearer token to a maker_id, so refreshing or rotating the token keeps the same bucket — and your client IP on public calls. Going over budget returns RESOURCE_EXHAUSTED (gRPC status 8) without ever invoking the handler; back off exponentially and retry — buckets refill continuously. No Retry-After header is sent.
Default limits, applied per key:
| Class | Applies to | Limit |
|---|---|---|
| Unary reads | All unary RPCs — MarketDataService (GetBook, ListPairs), StatsService, HistoricalService, NodeService, the AuthService handshake, and MakerService reads | 50 requests/sec |
| Transactions | TxService.SubmitTx | 10 tx/sec and 300 tx/min (both apply) |
| Streams | Server-streaming RPCs (Subscribe, SubscribeFills, SubscribeBlockhash, …) | 100 concurrent streams |
A few consequences worth knowing:
- Buckets start full. Each refills at its steady rate but tolerates a one-second burst first — up to 50 reads or 10 transactions back-to-back before throttling kicks in.
- Streams hold a slot, not a per-message charge. One long-lived
Subscribecounts as a single connection against your 100 slots until it closes — it doesn't draw down the per-second read bucket. Prefer a single long-lived stream over re-pollingGetBook, and reconnect with backoff rather than tearing down and reopening per event. AuthService.RequestLoginCodeadds a second limit of one code per email per minute, enforced inside the handler. For enumeration resistance the RPC always returns OK — a throttled request simply doesn't send a new code.- Limits are configurable server-side and can be raised per maker. High-throughput integrators who hit these ceilings should get in touch.
See Errors for the RESOURCE_EXHAUSTED mapping and Market data for polling cadence guidance.
