Reference

HTTP API

Everything this site does goes through one JSON API. Read endpoints are public and unauthenticated, so the protocol's state can be audited by anyone with curl.

Clustermainnet
Program6KZLGdp5…FczoUr13
Global state (PDA, seed "state")BFM88ZRx…q43wxyjT
Vault authority (PDA, seed "vault")B3Zz1LyU…t7F6bjfW
GOON mint bound to this deploymentnone yet
Goon Vault token accountcreated when the mint is bound
APIhttps://api-production-bffee4f7.up.railway.app/v1
Current period index…

Conventions#

  • All routes are under /v1. Requests and responses are JSON.
  • Token amounts are raw-unit decimal strings with six decimals: "1000000" is 1 GOON.
  • Goon Power is integer milli-GP: 1000 is 1 GP.
  • Times are unix seconds.
  • Authenticated routes take Authorization: Bearer <token>.
  • The complete typed contract is packages/shared/src/api.ts.
Error body (any non-2xx)
{ "error": { "code": "checkpoint_not_due", "message": "The next checkpoint is not due yet" } }

Authentication#

Sign-in is a wallet signature over a plain-text message. It costs nothing and cannot move funds.

Sign-in message
<domain> wants you to sign in with your Solana account:
<wallet>

Sign in to Proof of Goon. This costs nothing and cannot move funds.

URI: <site url>
Version: 1
Chain ID: solana:<cluster>
Nonce: <single-use nonce>
Issued At: <ISO time>
Expiration Time: <ISO time>
RouteBodyReturns
POST /auth/nonce{ wallet }{ nonce, message, expiresAt }. The nonce lives five minutes.
POST /auth/verify{ wallet, nonce, signature }{ token, expiresAt, wallet, isAdmin }. The signature is base58 ed25519 over the message bytes.
GET /meStatus, today's score by source, streak, totals, rank.
  • A nonce is consumed on the first verification attempt, successful or not.
  • The message binds the domain and the chain, so a signature for one deployment is useless on another.
  • Tokens last seven days. Admin rights are re-read from configuration on every request, not trusted from the token.

Public#

RouteReturns
GET /protocolCluster, program, mint, vault, mining status, epoch clock, emission config, bonding-curve progress, the active scoring config, headline stats.
GET /leaderboard?scope=today|all&limit=50Ranked wallets with Goon Power, streak and lifetime allocation.
GET /epochs?limit=30The open epoch followed by settled ones: status, miners, pool, distributed, root, data hash, publish signature.
GET /epochs/:periodOne settled epoch.
GET /epochs/:period/distributionThe canonical distribution file, byte for byte.
GET /claims/:walletCumulative, claimed and claimable amounts, the Merkle proof, and any pending allocation.
GET /issuersActive integration issuers and their limits.
GET /contributions/showcaseApproved community contributions.

Goon Sessions#

RouteEffect
POST /sessions/startStart a session, or return the one already running. Body may carry { turnstileToken }.
GET /sessions/currentThe active session, the last finished one this epoch, and how many sessions have been used.
POST /sessions/:id/checkpointOpen the checkpoint that is due. 409 checkpoint_not_due if early.
POST /sessions/:id/checkpoint/:checkpointIdAnswer it: { answer }. Returns passed, reason, seconds credited and the updated session.
POST /sessions/:id/endEnd the session.
Answer shapes
strike:  { "presses": [1240, 2105, 3310] }     // ms since the round began, one per seam
signal:  { "input": [2, 0, 5, 1] }             // flag indices, in order
tally:   { "count": 8 }

Daily challenges#

RouteEffect
GET /challengesThe epoch's challenges with status and attempts used.
POST /challenges/:kind/startIssue this wallet's puzzle. kind is trivia, cipher, hatches or course.
POST /challenges/:kind/submit{ answer }. Returns passed, GP awarded, and for trivia the number correct.
Answer shapes
trivia:   { "choices": [3, 0, 2, 1, 1] }
cipher:   { "text": "born to goon forced to mine" }
hatches:  { "moves": [0, 7, 12, 18] }            // cell indices, row-major
course:   { "moves": "RRDDRRUR" }                // U, D, L, R

Contributions and proofs#

RouteEffect
POST /contributions{ category, title, url, description }. 409 duplicate if the link was ever submitted.
GET /contributions/mineYour submissions with status, score and review note.
POST /proofsSubmit a signed integration proof. No user session needed; the issuer's signature is the credential.
POST /proofs/revoke{ issuer_id, proof_id, signature }. Issuer-signed revocation, valid until the epoch settles.

Limits#

  • 240 requests a minute per address overall; 60 on gameplay routes; 20 on sign-in, session start, contribution and revocation routes.
  • Request bodies are capped at 64 KB.
  • Browsers are restricted by CORS to this site's origin. Server-to-server calls carry no origin and are allowed.