{"openapi":"3.1.0","info":{"title":"Reach Trading API","version":"3.1.0","description":"Public product data and authenticated account actions. Predictions are submitted only on X by mentioning @reachdottrading with a target and one source post. The website and API do not create or preview predictions. Participation and public data require no website login or wallet. Website player-profile pages redirect to X; the profile data API remains read-only. Optional X OAuth enables Your rank, saving a private payout address and funded reward claims. Saving an address requires no wallet connection or ownership signature. Gameplay remains free and independent of sign-in or a wallet. The first prize plan is $5,000, payable in native ETH on Robinhood Chain (4663) only after actual funding and finalization. A planned amount is not a funded balance."},"servers":[{"url":"https://reach.trading"}],"externalDocs":{"description":"Public data and API documentation","url":"https://reach.trading/docs/data"},"x-reach-prediction-entry":{"channel":"x","account":"reachdottrading","instructions":"https://reach.trading/how-it-works","replyExample":"@reachdottrading 100k views","likesExample":"@reachdottrading 2k likes","requirements":["Official X author identity with current blue verification","Active X intake and confirmation replies"],"websiteLoginRequired":false,"walletRequired":false,"mode":"points_only","metrics":["views","likes"],"payoutsEnabled":false,"dailyAcceptedPerAccount":5,"platformDailyEntryLimit":null,"acceptance":"Accepted predictions are durably recorded before the bot sends one image with alt text, without accompanying text or a link. Receipts remain available through the read-only public API. A mention alone does not prove acceptance.","dailyLimitNotice":{"eligibility":"Otherwise valid prediction from a currently blue-verified, public account after all five shared Views and Likes entries are used.","maximumPerAccountPerUtcDay":1,"createsPrediction":false,"consumesEntry":false,"format":"One image with alt text; no accompanying text, link or printed URL.","reset":"00:00 UTC","seasonCutoff":"If season entries close at or before the next reset, the card says no entries remain this season instead of promising new entries tomorrow."},"otherRejectedInputs":"Unclear, invalid, ineligible, duplicate and other rejected inputs receive no reply. Historical generic notice jobs remain silent.","changes":"Accepted predictions cannot be edited or canceled.","status":"https://reach.trading/api/status"},"x-reach-homepage-demos":{"description":"Homepage demo posts and rankings are frontend-only illustrations. They are not live X embeds or accepted predictions and do not claim celebrity participation.","includedInPublicApis":false,"includedInOfficialStandings":false,"authoritativeData":"Public APIs and official standings contain only actual players and recorded activity."},"components":{"securitySchemes":{"reachSession":{"type":"apiKey","in":"cookie","name":"__Host-reach_session"}},"schemas":{"PayoutWallet":{"type":"object","additionalProperties":false,"required":["address","savedAt","verifiedAt","version"],"properties":{"address":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$","not":{"const":"0x0000000000000000000000000000000000000000"}},"savedAt":{"type":["string","null"],"format":"date-time","description":"Recorded direct-save time. Null only for a historical verified recipient that has not been directly saved."},"verifiedAt":{"type":["string","null"],"format":"date-time","description":"Genuine historical proof for the same address, if any. Direct saves never create proof and their response returns null."},"version":{"type":"string","pattern":"^(0|[1-9][0-9]{0,18})$","description":"Nonnegative decimal integer string, at most 9223372036854775807. Read the current value from private /api/me.wallet.version; use \"0\" when no address exists."}}},"SavePayoutAddress":{"type":"object","additionalProperties":false,"required":["address","expectedAddress","expectedVersion"],"properties":{"address":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$","not":{"const":"0x0000000000000000000000000000000000000000"}},"expectedAddress":{"type":["string","null"],"pattern":"^0x[0-9a-fA-F]{40}$","not":{"const":"0x0000000000000000000000000000000000000000"},"description":"Current private /api/me.wallet.address, or null when no recipient exists."},"expectedVersion":{"type":"string","pattern":"^(0|[1-9][0-9]{0,18})$","description":"Nonnegative decimal integer string, at most 9223372036854775807. Read the current value from private /api/me.wallet.version; use \"0\" when no address exists."}}}}},"paths":{"/api/me":{"get":{"summary":"Current optional X session","responses":{"200":{"description":"Private, no-store authenticated boolean, optional user identity and wallet=null or {address,savedAt,verifiedAt,version}. A saved address is a recipient instruction, not ownership proof. Historical proof may remain in verifiedAt; a historical fallback has savedAt=null and version=\"0\". Public data never exposes either address or proof."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/auth/x":{"get":{"summary":"Begin read-only X OAuth with PKCE","parameters":[{"name":"returnTo","in":"query","schema":{"type":"string","enum":["/account","/leaderboard","/admin"],"default":"/account"}}],"responses":{"303":{"description":"Redirect directly to X authorization."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/wallet/address":{"post":{"summary":"Save the signed-in X account payout address","security":[{"reachSession":[]}],"description":"Sign in with X, enter the recipient address and select Save address. No wallet connection, ownership signature or transaction is required. Same origin and recent X authentication are required. The service compares both expected values and advances the version on a new save. Repeating the same Idempotency-Key and command returns the original receipt without another write, even after a later save; read /api/me for the current address. A saved instruction does not fund a reward or redirect a queued or in-flight transfer.","parameters":[{"name":"X-Reach-Account-Id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Private /api/me.user.id for the active X session. This expectation does not authenticate the caller."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Retain the same UUID when retrying an identical save after an uncertain response."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavePayoutAddress"}}}},"responses":{"200":{"description":"Private, no-store save receipt. verifiedAt is null; saving an address does not manufacture ownership proof.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["accountId","wallet"],"properties":{"accountId":{"type":"string","format":"uuid"},"wallet":{"allOf":[{"$ref":"#/components/schemas/PayoutWallet"},{"type":"object","properties":{"savedAt":{"type":"string","format":"date-time"},"verifiedAt":{"type":"null"},"version":{"type":"string","pattern":"^[1-9][0-9]{0,18}$","description":"Nonnegative decimal integer string, at most 9223372036854775807. Read the current value from private /api/me.wallet.version; use \"0\" when no address exists."}}}]}}}}}},"400":{"description":"invalid_address, invalid_wallet_request or idempotency_key_required."},"401":{"description":"unauthenticated: sign in with X."},"403":{"description":"reauth_required, account_unavailable or same-origin check failed."},"409":{"description":"account_changed, payout_address_changed, request_conflict or payout_address_locked. Refresh the current account/address; an in-flight payout cannot be redirected."},"429":{"description":"rate_limited: retry after the reported interval."},"503":{"description":"payout_address_unavailable: the save could not be confirmed."}}}},"/api/account/wallet/challenge":{"post":{"deprecated":true,"summary":"Legacy ownership-proof challenge","security":[{"reachSession":[]}],"description":"Historical compatibility only. The current Save address flow uses /api/wallet/address and requires no ownership proof. This legacy route requires same origin, recent X authentication and X-Reach-Account-Id matching the session user. Body: {address}. Returns challengeId, exact message and expiry.","responses":{"200":{"description":"One-time, domain and session-bound legacy challenge."},"401":{"description":"Sign in with X."},"403":{"description":"Account, origin or recent authentication check failed."}}}},"/api/account/wallet":{"post":{"deprecated":true,"summary":"Legacy ownership-proof completion","security":[{"reachSession":[]}],"description":"Historical compatibility only; not required by the current Save address flow. Body: {challengeId,signature}. Same origin, account expectation and recent authentication are required. Historical proof cannot redirect an in-flight payment.","responses":{"200":{"description":"Historical wallet address and genuine verifiedAt."},"400":{"description":"Invalid, expired or used proof."},"409":{"description":"Conflicting or in-flight wallet change."}}}},"/api/season-prizes":{"get":{"summary":"Published prize plan and funding state","parameters":[{"name":"seasonId","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Current official season plan by default: USD amount, funding state and exact Top 25 rank shares. Planned does not mean funded. Payouts use native ETH on Robinhood Chain."},"404":{"description":"No prize plan."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/account/rewards":{"get":{"summary":"Rewards belonging to the authenticated immutable X account","description":"Requires X-Reach-Account-Id matching the current session user. Responses are private and never cached.","security":[{"reachSession":[]}],"responses":{"200":{"description":"Private reward obligations, payout state and server-determined claimAllowed. A missing payout address does not remove an earned funded entitlement."},"401":{"description":"Sign in with X."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/account/rewards/{id}/claim":{"post":{"summary":"Claim one eligible funded reward","security":[{"reachSession":[]}],"description":"Requires same origin, recent auth, expected account header and Idempotency-Key. The obligation is shared with automatic payouts and cannot be paid twice. Disabled without actual native ETH funding on Robinhood Chain (4663), a recorded conversion quote, gas and an enabled matching treasury signer. Queued recipients remain fixed.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Existing or newly reserved claim state; not proof of a confirmed payment."},"401":{"description":"Sign in with X."},"409":{"description":"Reward or payout address is not claimable."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/status":{"get":{"summary":"Official season, entry and X bot readiness","responses":{"200":{"description":"Points mode, supported metrics, dataReady, prediction and bot readiness, with blockers. The official season includes classification, durationHours=48 and entryHours=24. A draft season has status=draft and null startsAt, entriesCloseAt, endsAt and finalizedAt. Deployment does not start it. This read-only snapshot does not prove a successful reply."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/leaderboard":{"get":{"summary":"Official season Top 25 and a separate Search Username result","parameters":[{"name":"season","in":"query","schema":{"type":"string","format":"uuid"},"description":"Optional official season ID. Test-season IDs are unavailable to the public board. Omit for the current official season, including its unscheduled draft."},{"name":"handle","in":"query","schema":{"type":"string","pattern":"^@?[A-Za-z0-9_]{1,15}$"},"description":"Optional exact X handle submitted through Search Username. Returns watched separately, even outside the Top 25. Does not filter the public standings, authenticate the viewer or establish account ownership."}],"responses":{"200":{"description":"season (id, number, classification, durationHours, entryHours, startsAt, entriesCloseAt, endsAt, finalizedAt, status), entries (at most 25), total, pendingPredictions, watched, watchedHandle and fetchedAt. Only official seasons appear; test-season predictions remain separate. A draft has all dates null, no entries and no admission. The owner starts Season 1 later through admin: 48 hours total, entries during the first 24, then 24 hours for settlement. Deployment never starts it automatically. Rankings use fixed season membership and final scores only; pending players can have zero points. Points remain exact decimal values. Final rankings freeze after every result settles and the final five-minute integrity window passes. Processing delays keep status=settling. Old period/search/pagination filters are not supported."},"400":{"description":"Invalid or unsupported filter."},"404":{"description":"Season unavailable."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/predictions":{"get":{"summary":"Public prediction records","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":1000000}},{"name":"view","in":"query","schema":{"type":"string","enum":["all","active","history"],"default":"all"},"description":"Active includes accepted and review. History includes won, lost and void."},{"name":"handle","in":"query","schema":{"type":"string","maxLength":15}},{"name":"season","in":"query","schema":{"type":"string","format":"uuid"},"description":"Optional official season UUID. Restricts rows and total to that season and returns seasonId. Test seasons cannot be requested through this filter; public player history remains available separately."},{"name":"status","in":"query","schema":{"type":"string","enum":["accepted","review","won","lost","void"]}}],"responses":{"200":{"description":"Current records with total, limit, offset, hasMore and fetchedAt. Counts and points use decimal strings to preserve exact values. Each prediction and snapshot includes metric=views|likes. Legacy field names targetViews, baselineViews and views refer to counts of that recorded metric; they are not always impressions."},"400":{"description":"Invalid pagination or filter."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/profiles/{handle}":{"get":{"summary":"Read-only player data, counts and paginated predictions","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_]{1,15}$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":1000000}},{"name":"view","in":"query","schema":{"type":"string","enum":["all","active","history"],"default":"all"},"description":"Active includes accepted and review. History includes won, lost and void."}],"responses":{"200":{"description":"Current records with total, limit, offset, hasMore and fetchedAt. Counts and points use decimal strings to preserve exact values. Each prediction and snapshot includes metric=views|likes. Legacy field names targetViews, baselineViews and views refer to counts of that recorded metric; they are not always impressions."},"400":{"description":"Invalid pagination or filter."},"404":{"description":"Profile unavailable."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/predictions/{id}":{"get":{"summary":"Prediction receipt and recorded evidence","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Fixed acceptance terms, seasonId (null for historical unseasoned records), status, scoring version and recorded measurement evidence."},"404":{"description":"Prediction unavailable."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/api/predictions/{id}/image":{"get":{"summary":"Frozen prediction acceptance image","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Frozen metric, starting count, target, acceptance time, deadline and potential points. Optional historical totals are not required or reconstructed.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Prediction unavailable or no historical acceptance snapshot was recorded."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}},"/agent.json":{"get":{"summary":"Machine-readable product rules and current availability","responses":{"200":{"description":"Product description, rules, limitations and live status."},"503":{"description":"The backing service is unavailable. Do not interpret this as an empty list."}}}}}}