{"openapi":"3.1.0","info":{"title":"FomoData API","version":"1.0.0","description":"Profiles, Trade Theses, token activity and realtime events for Fomo through one clean API. FomoData is an independent developer platform and is not affiliated with or endorsed by FOMO Labs Inc."},"servers":[{"url":"https://fomodata.dev"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key: `Authorization: Bearer fd_test_…` or `fd_live_…`. Never send keys in URLs."}},"schemas":{"KeyInfo":{"type":"object","properties":{"object":{"type":"string","enum":["api_key"]},"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","example":"fd_test_Ab12"},"environment":{"type":"string","enum":["test","live"]},"livemode":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"string"}},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string"}},"required":["id","name","plan"]},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["object","id","name","prefix","environment","livemode","scopes","project","organization","created_at","expires_at"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","example":"invalid_request"},"code":{"type":"string","example":"INVALID_TOKEN"},"message":{"type":"string","example":"Token could not be resolved."},"request_id":{"type":"string","example":"req_6Yq1Hn0bVx3LmT8sRk2Wc4"},"param":{"type":"string"},"details":{},"doc_url":{"type":"string"}},"required":["type","code","message","request_id"]}},"required":["error"]},"Profile":{"type":"object","properties":{"object":{"type":"string","enum":["profile"]},"id":{"type":"string","example":"fp_4KZq8mXw2T0aN6rB1cYd9E"},"handle":{"type":"string","example":"@milo"},"display_name":{"type":["string","null"],"example":"Milo"},"avatar_url":{"type":["string","null"],"format":"uri"},"profile_url":{"type":["string","null"],"format":"uri","example":"https://fomo.family/profile/milo"},"bio":{"type":["string","null"]},"verified":{"type":["boolean","null"]},"source":{"type":"string","enum":["fomo","sandbox"],"description":"Where the data came from. `sandbox` = clearly-labelled test fixtures."},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z","description":"Account creation time upstream, when known."},"first_seen_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z","description":"When FomoData first observed this profile."},"updated_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"source_updated_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"stale":{"type":"boolean"},"wallet":{"$ref":"#/components/schemas/Wallet"}},"required":["object","id","handle","display_name","avatar_url","profile_url","bio","verified","source","livemode","created_at","first_seen_at","updated_at","source_updated_at"]},"Wallet":{"type":"object","properties":{"address":{"type":"string"},"network":{"type":"string","example":"evm"}},"required":["address","network"],"description":"Only present when the Wallets API is enabled and the association is public/authorized."},"ThesisList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Thesis"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["object","data","next_cursor","has_more"]},"Thesis":{"type":"object","properties":{"object":{"type":"string","enum":["thesis"]},"id":{"type":"string","example":"th_7Hq2LmZx9RkT4bVn0sYc3D"},"profile":{"$ref":"#/components/schemas/ProfileRef"},"token":{"$ref":"#/components/schemas/TokenRef"},"text":{"type":"string","example":"Course looks fast today. Running it back."},"public_url":{"type":["string","null"],"format":"uri","description":"Fomo exposes no public per-thesis permalink today, so this is null unless one becomes available."},"likes":{"type":["integer","null"]},"replies":{"type":["integer","null"]},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"source":{"type":"string","enum":["fomo","sandbox"],"description":"Where the data came from. `sandbox` = clearly-labelled test fixtures."},"livemode":{"type":"boolean"}},"required":["object","id","profile","token","text","public_url","likes","replies","created_at","updated_at","source","livemode"]},"ProfileRef":{"type":"object","properties":{"id":{"type":"string","example":"fp_4KZq8mXw2T0aN6rB1cYd9E"},"handle":{"type":"string","example":"@milo"},"display_name":{"type":["string","null"],"example":"Milo"},"avatar_url":{"type":["string","null"],"format":"uri"}},"required":["id","handle","display_name","avatar_url"]},"TokenRef":{"type":"object","properties":{"id":{"type":"string","example":"tk_9bF2kLmQ0sVx7RtY3nHc1A"},"symbol":{"type":"string","example":"$RUN"},"name":{"type":["string","null"],"example":"Run"},"chain":{"type":"string","example":"robinhood"},"address":{"type":"string","example":"0x5a4d1f3c0f6e2b8d9a7c4e1f0b3d6a9c2e5f8a1b"}},"required":["id","symbol","name","chain","address"]},"ThesisVerification":{"type":"object","properties":{"object":{"type":"string","enum":["thesis_verification"]},"verified":{"type":"boolean"},"profile_id":{"type":["string","null"]},"thesis_id":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"token":{"type":["string","null"],"example":"$RUN"},"checks":{"type":"object","properties":{"identity":{"type":"boolean"},"token":{"type":"boolean"},"time_window":{"type":"boolean"},"thesis_exists":{"type":"boolean"},"not_deleted":{"type":"boolean"},"contains":{"type":["boolean","null"]}},"required":["identity","token","time_window","thesis_exists","not_deleted","contains"]},"reason":{"type":"string","enum":["VERIFIED","PROFILE_NOT_FOUND","TOKEN_NOT_FOUND","NO_THESIS_IN_WINDOW","TEXT_NOT_FOUND","THESIS_DELETED"],"description":"Machine-readable outcome. Verification never judges thesis quality, sentiment or accuracy."},"freshness":{"type":"object","properties":{"checked_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"upstream_synced_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"served_from":{"type":"string","enum":["live_sync","cache"]}},"required":["checked_at","upstream_synced_at","served_from"]},"livemode":{"type":"boolean"}},"required":["object","verified","profile_id","thesis_id","created_at","token","checks","reason","freshness","livemode"]},"VerifyThesisRequest":{"type":"object","properties":{"handle":{"type":"string","maxLength":64,"description":"Author handle. Pass this or `profile_id`.","example":"@milo"},"profile_id":{"type":"string","maxLength":64,"description":"FomoData profile id (`fp_…`) or Fomo user id. Pass this or `handle`."},"token":{"type":"string","minLength":1,"maxLength":140,"description":"Token reference (`$RUN`, `tk_…`, address, `chain:address`).","example":"$RUN"},"chain":{"type":"string","maxLength":32,"description":"Narrows a symbol that exists on several chains.","example":"robinhood"},"created_after":{"type":"string","minLength":1,"description":"Window start (ISO-8601, inclusive).","example":"2026-10-07T10:00:00Z"},"created_before":{"type":"string","description":"Window end (ISO-8601, inclusive). Defaults to now.","example":"2026-10-07T10:10:00Z"},"contains":{"type":"string","maxLength":500,"description":"Optional case-insensitive substring the thesis text must contain."}},"required":["token","created_after"]},"Token":{"type":"object","properties":{"object":{"type":"string","enum":["token"]},"id":{"type":"string"},"symbol":{"type":"string","example":"$RUN"},"name":{"type":["string","null"]},"chain":{"type":"string","example":"robinhood"},"chain_id":{"type":["integer","null"],"example":4663},"address":{"type":"string"},"logo_url":{"type":["string","null"],"format":"uri"},"fomo_url":{"type":["string","null"],"format":"uri"},"thesis_count":{"type":"integer","description":"Theses FomoData has ingested for this token (see metrics_scope)."},"unique_thesis_authors":{"type":"integer"},"recent_thesis_count":{"type":"integer","description":"Theses in the last 24 hours."},"first_seen_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"last_activity_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"metrics_scope":{"type":"string","enum":["ingested"],"description":"Counts cover theses FomoData has observed since first_seen_at — not Fomo's all-time totals."},"source":{"type":"string","enum":["fomo","sandbox"],"description":"Where the data came from. `sandbox` = clearly-labelled test fixtures."},"livemode":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"source_updated_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"stale":{"type":"boolean"}},"required":["object","id","symbol","name","chain","chain_id","address","logo_url","fomo_url","thesis_count","unique_thesis_authors","recent_thesis_count","first_seen_at","last_activity_at","metrics_scope","source","livemode","updated_at","source_updated_at"]},"TokenActivity":{"type":"object","properties":{"object":{"type":"string","enum":["token_activity"]},"token":{"$ref":"#/components/schemas/TokenRef"},"thesis_count_1h":{"type":"integer"},"thesis_count_24h":{"type":"integer"},"unique_authors_24h":{"type":"integer"},"last_activity_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"timeline":{"type":"array","items":{"type":"object","properties":{"bucket_start":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"theses":{"type":"integer"},"unique_authors":{"type":"integer"}},"required":["bucket_start","theses","unique_authors"]},"description":"Hourly buckets, newest last, last 24h."},"recent_theses":{"type":"array","items":{"$ref":"#/components/schemas/Thesis"}},"metrics_scope":{"type":"string","enum":["ingested"]},"livemode":{"type":"boolean"},"computed_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["object","token","thesis_count_1h","thesis_count_24h","unique_authors_24h","last_activity_at","timeline","recent_theses","metrics_scope","livemode","computed_at"]},"ThesisVelocity":{"type":"object","properties":{"object":{"type":"string","enum":["thesis_velocity"]},"token":{"$ref":"#/components/schemas/TokenRef"},"last_5m":{"type":"integer"},"last_1h":{"type":"integer"},"previous_1h":{"type":"integer"},"change_pct":{"type":["number","null"],"example":186.2,"description":"null when previous_1h is 0."},"metrics_scope":{"type":"string","enum":["ingested"]},"livemode":{"type":"boolean"},"computed_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["object","token","last_5m","last_1h","previous_1h","change_pct","metrics_scope","livemode","computed_at"]},"SearchResult":{"type":"object","properties":{"object":{"type":"string","enum":["search_result"]},"query":{"type":"string"},"theses":{"type":"array","items":{"$ref":"#/components/schemas/Thesis"}},"profiles":{"type":"array","items":{"$ref":"#/components/schemas/Profile"}},"tokens":{"type":"array","items":{"$ref":"#/components/schemas/Token"}},"livemode":{"type":"boolean"}},"required":["object","query","theses","profiles","tokens","livemode"]},"SemanticSearchRequest":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500,"example":"early AI infrastructure theses"},"limit":{"type":"integer","minimum":1,"maximum":50}},"required":["query"]},"EventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["object","data","next_cursor","has_more"]},"Event":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","example":"evt_2Nf8QpLx0VbT6mRz4kWc1S"},"type":{"$ref":"#/components/schemas/EventType"},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"livemode":{"type":"boolean"},"source":{"type":"string","enum":["fomo","sandbox","fomodata"],"description":"`fomodata` = derived by FomoData from authorized upstream events (activity, velocity)."},"test":{"type":"boolean","description":"true for dashboard/API-generated test events (never real Fomo activity)."},"data":{"anyOf":[{"$ref":"#/components/schemas/ThesisCreatedData"},{"$ref":"#/components/schemas/ProfileUpdatedData"},{"$ref":"#/components/schemas/TokenActivityData"},{"$ref":"#/components/schemas/ThesisVelocityData"}]}},"required":["object","id","type","created_at","livemode","source","data"]},"EventType":{"type":"string","enum":["thesis.created","profile.updated","token.activity","token.thesis_velocity"]},"ThesisCreatedData":{"type":"object","properties":{"thesis_id":{"type":"string"},"profile":{"$ref":"#/components/schemas/ProfileRef"},"token":{"$ref":"#/components/schemas/TokenRef"},"text":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"public_url":{"type":["string","null"],"format":"uri"}},"required":["thesis_id","profile","token","text","created_at","public_url"]},"ProfileUpdatedData":{"type":"object","properties":{"profile":{"$ref":"#/components/schemas/Profile"},"changed":{"type":"array","items":{"type":"string"}}},"required":["profile","changed"]},"TokenActivityData":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/TokenRef"},"thesis_count_1h":{"type":"integer"},"thesis_count_24h":{"type":"integer"},"unique_authors_24h":{"type":"integer"},"latest_thesis_id":{"type":["string","null"]},"last_activity_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["token","thesis_count_1h","thesis_count_24h","unique_authors_24h","latest_thesis_id","last_activity_at"]},"ThesisVelocityData":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/TokenRef"},"last_5m":{"type":"integer"},"last_1h":{"type":"integer"},"previous_1h":{"type":"integer"},"change_pct":{"type":["number","null"]},"computed_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["token","last_5m","last_1h","previous_1h","change_pct","computed_at"]},"ProfileWallets":{"type":"object","properties":{"object":{"type":"string","enum":["profile_wallets"]},"profile":{"$ref":"#/components/schemas/ProfileRef"},"wallets":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/Wallet"},{"type":"object","properties":{"observed_at":{"type":"string"}},"required":["observed_at"]}]}},"livemode":{"type":"boolean"}},"required":["object","profile","wallets","livemode"]},"TestThesisResult":{"type":"object","properties":{"object":{"type":"string","enum":["test_thesis"]},"thesis":{"$ref":"#/components/schemas/Thesis"},"event":{"$ref":"#/components/schemas/Event"}},"required":["object","thesis","event"]},"TestThesisRequest":{"type":"object","properties":{"handle":{"type":"string","minLength":1,"maxLength":41,"description":"Author handle for the test thesis.","example":"@sbx_milo"},"token":{"type":"string","minLength":1,"maxLength":140,"description":"Sandbox token: `$RUN`, `$SEEK`, `$RACE`, `$TAG`, `$ART`, `$CRAFT`, or any new symbol (created as a test token for your project).","example":"$RUN"},"text":{"type":"string","minLength":1,"maxLength":2000,"example":"Testing my race-entry webhook."}},"required":["handle","token","text"]},"WebhookList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["object","data","next_cursor","has_more"]},"Webhook":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string","example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"url":{"type":"string","format":"uri"},"description":{"type":["string","null"]},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"filters":{"$ref":"#/components/schemas/WebhookFilters"},"status":{"type":"string","enum":["enabled","disabled","disabled_failing"]},"secret_prefix":{"type":"string","example":"whsec_Ab12"},"livemode":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["object","id","url","description","events","filters","status","secret_prefix","livemode","created_at","updated_at"]},"WebhookFilters":{"type":"object","properties":{"token":{"type":"array","items":{"type":"string"},"description":"Token refs ($SYMBOL, address or tk_ id)."},"handle":{"type":"array","items":{"type":"string"}},"chain":{"type":"array","items":{"type":"string"}}}},"WebhookWithSecret":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"Signing secret — shown ONLY in the create/rotate response."}},"required":["secret"]}]},"CreateWebhookRequest":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"Public https endpoint. Private, loopback, link-local and metadata addresses are refused.","example":"https://example.com/hooks/fomodata"},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"},"minItems":1,"maxItems":10,"example":["thesis.created"]},"filters":{"allOf":[{"$ref":"#/components/schemas/WebhookFilters"},{"description":"Optional: only events matching every given dimension (values within a dimension are OR-ed).","example":{"token":["$RUN"]}}]},"description":{"type":["string","null"],"maxLength":500,"example":"Race entries"}},"required":["url","events"]},"UpdateWebhookRequest":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"},"minItems":1,"maxItems":10},"filters":{"allOf":[{"$ref":"#/components/schemas/WebhookFilters"},{"description":"Replaces the filters. Send `{}` to clear."}]},"description":{"type":["string","null"],"maxLength":500},"status":{"type":"string","enum":["enabled","disabled"],"description":"Re-enabling a `disabled_failing` endpoint resets its failure streak."}}},"DeletedWebhook":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"]},"WebhookDelivery":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_delivery"]},"id":{"type":"string"},"webhook_id":{"type":"string"},"event_id":{"type":"string"},"event_type":{"$ref":"#/components/schemas/EventType"},"status":{"type":"string","enum":["pending","delivered","failed","retrying"]},"attempt":{"type":"integer"},"max_attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"latency_ms":{"type":["integer","null"]},"next_attempt_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"},"is_replay":{"type":"boolean"},"is_test":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","example":"2026-10-07T10:04:12.000Z"},"delivered_at":{"type":["string","null"],"format":"date-time","example":"2026-10-07T10:04:12.000Z"}},"required":["object","id","webhook_id","event_id","event_type","status","attempt","max_attempts","response_status","latency_ms","next_attempt_at","is_replay","is_test","created_at","delivered_at"]},"WebhookDeliveryList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["object","data","next_cursor","has_more"]}},"parameters":{}},"paths":{"/v1/me":{"get":{"tags":["Meta"],"summary":"Inspect the current API key","description":"Returns the key's project, organization, plan, environment and scopes. Works with any valid key.","security":[{"bearerAuth":[]}],"x-scopes":[],"x-rate-class":"standard","responses":{"200":{"description":"Key info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyInfo"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events/stream":{"get":{"tags":["Streams"],"summary":"Stream events (Server-Sent Events)","description":"Server-Sent Events stream of realtime events, filtered like webhooks. Frames: `id: <cursor>`, `event: <type>`, `data: <Event JSON>`; a `: ping` comment every 15 s.\n\nReconnect with the `Last-Event-ID` header (browsers do this automatically) to resume after the last cursor — up to 1,000 missed events within your plan's history window are replayed first.\n\nCounts toward your plan's concurrent stream connections (WebSocket + SSE). Test keys only receive test-mode events (sandbox data, `livemode: false`).","security":[{"bearerAuth":[]}],"x-scopes":["streams:read"],"x-feature-flag":"STREAMS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","description":"Comma-separated event types (default: all).","example":"thesis.created"},"required":false,"description":"Comma-separated event types (default: all).","name":"types","in":"query"},{"schema":{"type":"string","description":"Comma-separated token refs ($SYMBOL, address, chain:address or tk_ id).","example":"$RUN"},"required":false,"description":"Comma-separated token refs ($SYMBOL, address, chain:address or tk_ id).","name":"token","in":"query"},{"schema":{"type":"string","description":"Comma-separated Fomo handles.","example":"@milo"},"required":false,"description":"Comma-separated Fomo handles.","name":"handle","in":"query"},{"schema":{"type":"string","description":"Comma-separated chains.","example":"robinhood"},"required":false,"description":"Comma-separated chains.","name":"chain","in":"query"},{"schema":{"type":"string","description":"Resume after this cursor (an event frame's `id`). `Last-Event-ID` takes precedence."},"required":false,"description":"Resume after this cursor (an event frame's `id`). `Last-Event-ID` takes precedence.","name":"from_cursor","in":"query"},{"schema":{"type":"string","description":"Resume cursor (seq of the last event received)."},"required":false,"description":"Resume cursor (seq of the last event received).","name":"last-event-id","in":"header"}],"responses":{"200":{"description":"text/event-stream of Event objects","content":{"text/event-stream":{"schema":{"type":"string","example":"id: 1042\nevent: thesis.created\ndata: {\"object\":\"event\",\"id\":\"evt_…\",\"type\":\"thesis.created\",…}\n\n"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/profiles/{ref}":{"get":{"tags":["Profiles"],"summary":"Retrieve a profile","description":"Resolve a Fomo identity by handle (`@milo`), FomoData id (`fp_…`) or Fomo user id.\n\nResolution order: FomoData's index first; for live keys an unknown handle is looked up once through the authorized upstream (misses are cached for 10 minutes). Only public profile metadata is returned — never PnL, balances or private account data.\n\nLive keys read real Fomo data FomoData ingested from its authorized upstream; test keys read clearly-labelled sandbox data (`livemode: false`, `source: \"sandbox\"`). Objects carry `updated_at` / `source_updated_at`. When cached data is served because the upstream could not be reached, the object has `stale: true`.","security":[{"bearerAuth":[]}],"x-scopes":["profiles:read"],"x-feature-flag":"PROFILES_API_ENABLED","x-rate-class":"heavy","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80,"description":"`@milo`, `milo`, a FomoData id (`fp_…`) or a Fomo user id.","example":"@milo"},"required":true,"description":"`@milo`, `milo`, a FomoData id (`fp_…`) or a Fomo user id.","name":"ref","in":"path"}],"responses":{"200":{"description":"The profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Profile"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/profiles":{"get":{"tags":["Profiles"],"summary":"Look up a profile","description":"Look up one profile by exactly one of `id`, `handle` or `fomo_user_id`.\n\nResolution order: FomoData's index first; for live keys an unknown handle is looked up once through the authorized upstream (misses are cached for 10 minutes). Only public profile metadata is returned — never PnL, balances or private account data.","security":[{"bearerAuth":[]}],"x-scopes":["profiles:read"],"x-feature-flag":"PROFILES_API_ENABLED","x-rate-class":"heavy","parameters":[{"schema":{"type":"string","maxLength":64,"description":"FomoData profile id.","example":"fp_4KZq8mXw2T0aN6rB1cYd9E"},"required":false,"description":"FomoData profile id.","name":"id","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"Fomo handle, with or without `@`.","example":"@milo"},"required":false,"description":"Fomo handle, with or without `@`.","name":"handle","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"Fomo's stable user id (survives handle renames)."},"required":false,"description":"Fomo's stable user id (survives handle renames).","name":"fomo_user_id","in":"query"}],"responses":{"200":{"description":"The profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Profile"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/theses":{"get":{"tags":["Theses"],"summary":"List theses","description":"Trade Theses from FomoData's index, newest first by default. Combine filters freely.\n\nQueries are limited to your plan's history window: an explicit lower bound earlier than that returns 403 `HISTORY_LIMIT`; without one, results are implicitly limited to the window.\n\nLive keys read real Fomo data FomoData ingested from its authorized upstream; test keys read clearly-labelled sandbox data (`livemode: false`, `source: \"sandbox\"`).","security":[{"bearerAuth":[]}],"x-scopes":["theses:read"],"x-feature-flag":"THESES_API_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","maxLength":200,"description":"Profile reference: `fp_…`, `@handle` or Fomo user id.","example":"@milo"},"required":false,"description":"Profile reference: `fp_…`, `@handle` or Fomo user id.","name":"profile","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Author handle, with or without `@`.","example":"@milo"},"required":false,"description":"Author handle, with or without `@`.","name":"handle","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Token reference: `tk_…`, address, `chain:address`, `$RUN` or `RUN`. A symbol matches every token with that symbol unless `chain` narrows it.","example":"$RUN"},"required":false,"description":"Token reference: `tk_…`, address, `chain:address`, `$RUN` or `RUN`. A symbol matches every token with that symbol unless `chain` narrows it.","name":"token","in":"query"},{"schema":{"type":"string","maxLength":32,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","example":"robinhood"},"required":false,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","name":"chain","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"ISO-8601 lower bound (inclusive).","example":"2026-10-07T10:00:00Z"},"required":false,"description":"ISO-8601 lower bound (inclusive).","name":"created_after","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"ISO-8601 upper bound (inclusive).","example":"2026-10-07T11:00:00Z"},"required":false,"description":"ISO-8601 upper bound (inclusive).","name":"created_before","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Relative lower bound: `90s`, `30m`, `1h`, `7d`. Combined with `created_after`, the later bound wins.","example":"1h"},"required":false,"description":"Relative lower bound: `90s`, `30m`, `1h`, `7d`. Combined with `created_after`, the later bound wins.","name":"since","in":"query"},{"schema":{"type":"string","enum":["created_at_desc","created_at_asc","likes_desc"],"description":"Sort order (default `created_at_desc`).","example":"created_at_desc"},"required":false,"description":"Sort order (default `created_at_desc`).","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Page size, 1–100 (default 25).","example":25},"required":false,"description":"Page size, 1–100 (default 25).","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":512,"description":"Opaque `next_cursor` from the previous page."},"required":false,"description":"Opaque `next_cursor` from the previous page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of theses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThesisList"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/theses/{id}":{"get":{"tags":["Theses"],"summary":"Retrieve a thesis","description":"One thesis with its author profile and token. `public_url` is null because Fomo exposes no per-thesis permalink.\n\nLive keys read real Fomo data FomoData ingested from its authorized upstream; test keys read clearly-labelled sandbox data (`livemode: false`, `source: \"sandbox\"`).","security":[{"bearerAuth":[]}],"x-scopes":["theses:read"],"x-feature-flag":"THESES_API_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","maxLength":64,"description":"Thesis id (`th_…`).","example":"th_7Hq2LmZx9RkT4bVn0sYc3D"},"required":true,"description":"Thesis id (`th_…`).","name":"id","in":"path"}],"responses":{"200":{"description":"The thesis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Thesis"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/verify/thesis":{"post":{"tags":["Theses"],"summary":"Verify a thesis","description":"Checks that the identity posted a thesis on the token inside the time window — and nothing else. Verification never judges thesis quality, sentiment, intelligence or accuracy.\n\nAlways 200 with `verified` true/false and a machine-readable `reason` (`VERIFIED`, `PROFILE_NOT_FOUND`, `TOKEN_NOT_FOUND`, `NO_THESIS_IN_WINDOW`, `TEXT_NOT_FOUND`, `THESIS_DELETED`). For live keys, when nothing matches and the window ended within the last 15 minutes, FomoData syncs the token's latest theses from its authorized upstream once and re-checks (`freshness.served_from: live_sync`). If that sync fails while the realtime feed is also down, the call returns 503 instead of a possibly-false negative.","security":[{"bearerAuth":[]}],"x-scopes":["theses:read"],"x-feature-flag":"THESES_API_ENABLED","x-rate-class":"verify","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyThesisRequest"}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThesisVerification"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. ambiguous token symbol)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tokens/{ref}":{"get":{"tags":["Tokens"],"summary":"Retrieve a token","description":"Normalized token metadata plus thesis counters. For live keys an unknown symbol is looked up once through the authorized upstream's token search.\n\nAll counts are derived from theses FomoData ingested from its authorized upstream since `first_seen_at` (`metrics_scope: \"ingested\"`) — not Fomo's all-time totals.\n\nLive keys read real Fomo data FomoData ingested from its authorized upstream; test keys read clearly-labelled sandbox data (`livemode: false`, `source: \"sandbox\"`). Objects carry `updated_at` / `source_updated_at`. When cached data is served because the upstream could not be reached, the object has `stale: true`.","security":[{"bearerAuth":[]}],"x-scopes":["tokens:read"],"x-feature-flag":"TOKENS_API_ENABLED","x-rate-class":"heavy","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":140,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","example":"$RUN"},"required":true,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","name":"ref","in":"path"},{"schema":{"type":"string","maxLength":32,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","example":"robinhood"},"required":false,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","name":"chain","in":"query"}],"responses":{"200":{"description":"The token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. ambiguous token symbol)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tokens/{ref}/activity":{"get":{"tags":["Tokens"],"summary":"Token activity","description":"Recent theses, unique posters and an hourly timeline for the last 24 hours.\n\nAll counts are derived from theses FomoData ingested from its authorized upstream since `first_seen_at` (`metrics_scope: \"ingested\"`) — not Fomo's all-time totals.","security":[{"bearerAuth":[]}],"x-scopes":["tokens:read"],"x-feature-flag":"TOKENS_API_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":140,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","example":"$RUN"},"required":true,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","name":"ref","in":"path"},{"schema":{"type":"string","maxLength":32,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","example":"robinhood"},"required":false,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","name":"chain","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"description":"How many recent theses to include (1–50, default 10).","example":10},"required":false,"description":"How many recent theses to include (1–50, default 10).","name":"recent","in":"query"}],"responses":{"200":{"description":"Token activity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenActivity"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. ambiguous token symbol)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tokens/{ref}/thesis-velocity":{"get":{"tags":["Tokens"],"summary":"Token thesis velocity","description":"Theses in the last 5 minutes and last hour vs the previous hour. `change_pct` is null when the previous hour had none.\n\nAll counts are derived from theses FomoData ingested from its authorized upstream since `first_seen_at` (`metrics_scope: \"ingested\"`) — not Fomo's all-time totals.","security":[{"bearerAuth":[]}],"x-scopes":["tokens:read"],"x-feature-flag":"TOKENS_API_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":140,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","example":"$RUN"},"required":true,"description":"Token reference: `tk_…` id, contract/mint address, `chain:address`, `$RUN` or `RUN` (case-insensitive). A symbol on several chains returns 409 `AMBIGUOUS_TOKEN` — pass `?chain=` or the address.","name":"ref","in":"path"},{"schema":{"type":"string","maxLength":32,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","example":"robinhood"},"required":false,"description":"Narrow to one chain, e.g. `robinhood`, `solana`, `base`. Test keys: `sandbox`.","name":"chain","in":"query"}],"responses":{"200":{"description":"Thesis velocity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThesisVelocity"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. ambiguous token symbol)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/search":{"get":{"tags":["Search"],"summary":"Search","description":"Full-text search over FomoData's local index of authorized data: theses (ranked by relevance), profiles (handle prefix, display name) and tokens (symbol prefix, name). Searches are never proxied to Fomo. Thesis results respect your plan's history window.\n\nLive keys read real Fomo data FomoData ingested from its authorized upstream; test keys read clearly-labelled sandbox data (`livemode: false`, `source: \"sandbox\"`).","security":[{"bearerAuth":[]}],"x-scopes":["search:read"],"x-feature-flag":"SEARCH_API_ENABLED","x-rate-class":"search","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Search text. `@handle` and `$SYMBOL` prefixes are understood.","example":"ai agents"},"required":true,"description":"Search text. `@handle` and `$SYMBOL` prefixes are understood.","name":"q","in":"query"},{"schema":{"type":"string","maxLength":40,"description":"Comma-separated subset of `theses,profiles,tokens` (default all).","example":"theses,profiles,tokens"},"required":false,"description":"Comma-separated subset of `theses,profiles,tokens` (default all).","name":"types","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"description":"Page size, 1–50 (default 10).","example":10},"required":false,"description":"Page size, 1–50 (default 10).","name":"limit","in":"query"}],"responses":{"200":{"description":"Search results grouped by type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/search/semantic":{"post":{"tags":["Search"],"summary":"Semantic search (coming soon)","description":"**COMING SOON.** Semantically relevant theses for a natural-language query, indexing only content authorized for search. Until semantic indexing ships this endpoint returns 404 `FEATURE_DISABLED`; use `GET /v1/search` for full-text search.","security":[{"bearerAuth":[]}],"x-scopes":["search:read"],"x-feature-flag":"SEMANTIC_SEARCH_ENABLED","x-rate-class":"search","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SemanticSearchRequest"}}}},"responses":{"200":{"description":"Search results (once available)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events":{"get":{"tags":["Events"],"summary":"List events","description":"Historical events, newest first, within your plan's history window.\n\nEvent types: `thesis.created`, `profile.updated`, `token.activity`, `token.thesis_velocity`. The same Event object is delivered over REST, SSE, WebSocket streams and webhooks; `id` is stable for deduplication. `source` is `fomo` for upstream events, `fomodata` for events FomoData derives from them (activity, velocity) and `sandbox` for labelled test data.","security":[{"bearerAuth":[]}],"x-scopes":["events:read"],"x-rate-class":"standard","parameters":[{"schema":{"type":"string","maxLength":200,"description":"Comma-separated event types to include.","example":"thesis.created"},"required":false,"description":"Comma-separated event types to include.","name":"types","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Page size, 1–100 (default 25).","example":25},"required":false,"description":"Page size, 1–100 (default 25).","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":512,"description":"Opaque `next_cursor` from the previous page."},"required":false,"description":"Opaque `next_cursor` from the previous page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events/{id}":{"get":{"tags":["Events"],"summary":"Retrieve an event","description":"Event types: `thesis.created`, `profile.updated`, `token.activity`, `token.thesis_velocity`. The same Event object is delivered over REST, SSE, WebSocket streams and webhooks; `id` is stable for deduplication. `source` is `fomo` for upstream events, `fomodata` for events FomoData derives from them (activity, velocity) and `sandbox` for labelled test data.","security":[{"bearerAuth":[]}],"x-scopes":["events:read"],"x-rate-class":"standard","middleware":[null],"parameters":[{"schema":{"type":"string","description":"Event id (`evt_…`).","example":"evt_2Nf8QpLx0VbT6mRz4kWc1S"},"required":true,"description":"Event id (`evt_…`).","name":"id","in":"path"}],"responses":{"200":{"description":"The event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/wallets/{ref}":{"get":{"tags":["Wallets"],"summary":"Public wallet associations","description":"Public, authorized wallet associations for a profile. **Disabled by default** (`WALLETS_API_ENABLED=false`): until wallet exposure is confirmed as permitted, this returns 404 `FEATURE_DISABLED` and the `wallets:read` scope cannot be granted.","security":[{"bearerAuth":[]}],"x-scopes":["wallets:read"],"x-feature-flag":"WALLETS_API_ENABLED","x-rate-class":"heavy","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":80,"description":"`@milo`, `milo`, a FomoData id (`fp_…`) or a Fomo user id.","example":"@milo"},"required":true,"description":"`@milo`, `milo`, a FomoData id (`fp_…`) or a Fomo user id.","name":"ref","in":"path"}],"responses":{"200":{"description":"Wallet associations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileWallets"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Upstream unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/test/theses":{"post":{"tags":["Testing"],"summary":"Create a test thesis","description":"**Test keys only** (live keys get 400 `TEST_MODE_ONLY`). Creates a sandbox thesis visible only to your project and emits a labelled `thesis.created` event (`livemode: false`, `source: \"sandbox\"`, `test: true`) to your project's test-mode webhooks and streams. Use it to exercise your integration end to end; it is never real Fomo activity.","security":[{"bearerAuth":[]}],"x-scopes":["theses:read"],"x-feature-flag":"THESES_API_ENABLED","x-rate-class":"standard","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestThesisRequest"}}}},"responses":{"201":{"description":"The test thesis and its event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestThesisResult"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. ambiguous token symbol)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","description":"Webhooks belong to the key's project and environment: a test key manages test-mode endpoints (sandbox events), a live key live endpoints.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","description":"1–100, default 25.","example":"25"},"required":false,"description":"1–100, default 25.","name":"limit","in":"query"},{"schema":{"type":"string","description":"`next_cursor` from the previous page."},"required":false,"description":"`next_cursor` from the previous page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Webhook endpoints, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Webhooks belong to the key's project and environment: a test key manages test-mode endpoints (sandbox events), a live key live endpoints.\n\nThe signing secret (`whsec_…`) is returned ONCE in this response. Every delivery carries `FomoData-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>`; reject timestamps older than 300 s. Failed deliveries retry after 1 min, 5 min, 30 min, 2 h and 12 h (6 attempts).","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}}},"responses":{"201":{"description":"Created — includes the secret once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithSecret"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Retrieve a webhook endpoint","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The webhook endpoint (never includes the secret)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Webhooks"],"summary":"Update a webhook endpoint","description":"Change the URL, subscribed events, filters, description, or enable/disable it.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}}},"responses":{"200":{"description":"The updated webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"Deletes the endpoint and its delivery log. Pending retries are cancelled.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedWebhook"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/rotate-secret":{"post":{"tags":["Webhooks"],"summary":"Rotate the signing secret","description":"Issues a new `whsec_…` secret, returned once. It takes effect immediately; the previous secret stops signing.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The webhook with its new secret (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithSecret"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test event","description":"Delivers a clearly-labelled fake `thesis.created` event (`test: true`, sandbox handle `@sbx_milo`) to this endpoint only. It is never real Fomo activity and is not sent to streams or other endpoints.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"The queued test delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List deliveries for a webhook","description":"Delivery log, newest first: status (pending, delivered, retrying, failed), attempt, response status, latency, event id.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"wh_8Tq3NkVz1LmB5xRc7pYd2F"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"1–100, default 25.","example":"25"},"required":false,"description":"1–100, default 25.","name":"limit","in":"query"},{"schema":{"type":"string","description":"`next_cursor` from the previous page."},"required":false,"description":"`next_cursor` from the previous page.","name":"cursor","in":"query"},{"schema":{"type":"string","enum":["pending","delivered","failed","retrying"],"description":"Only deliveries in this state."},"required":false,"description":"Only deliveries in this state.","name":"status","in":"query"}],"responses":{"200":{"description":"Deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhook-deliveries/{id}/replay":{"post":{"tags":["Webhooks"],"summary":"Replay a delivery","description":"Re-sends the SAME event (same `event.id`, so your deduplication still works) as a new delivery with `is_replay: true` and header `FomoData-Replay: true`.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:write"],"x-feature-flag":"WEBHOOKS_ENABLED","x-rate-class":"standard","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"example":"del_3Hq9LmZx1RkT4bVn0sYc7D"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"The new replay delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope, live access not approved, or history limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or feature disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}