KocAlgo: verifiable sports data for autonomous agents
1. Abstract
KocAlgo is an HTTP API that sells football and basketball data (live scores, results, match events, odds and football player statistics) to software agents, one request at a time. There are no accounts or API keys. Each request is paid with the x402 protocol (HTTP 402 Payment Required) in USDC on Algorand. Each paid endpoint publishes the x402 Bazaar discovery extension, so an agent that has never heard of KocAlgo can find it in a catalog, read its schemas and price, pay, and use the data. Every response is signed with Ed25519, and finalized results are committed to Algorand as hourly Merkle roots, so a consumer can check that the data it bought is the data we published, and when.
2. Problem
Autonomous agents increasingly need facts about the world: a prediction-market agent needs a final score, a trading or betting assistant needs live state, a research agent needs historical results. Today's sports APIs are built for humans and companies:
- Onboarding. Accounts, contracts and monthly plans do not fit an agent that needs ten requests once.
- Discovery. An agent has to be told the provider's URL in advance; it cannot search for "verified football results" and find one.
- Trust. A response is just JSON. A downstream contract or counterparty cannot tell whether the data was altered after it left the provider.
KocAlgo addresses all three: payment per request without onboarding, machine discovery, and cryptographic provenance.
3. System overview
- Ingestion. A worker reads live boards continuously (long-poll with a polling fallback) and scans today's and yesterday's fixtures every five minutes. Rows that do not match the expected source format are rejected and reported rather than guessed.
- Storage. Every match gets a canonical id. Score and status changes are written to an append-only change log with a monotonic cursor. A finalized result is immutable; a later correction becomes a new revision rather than an overwrite.
- API. An unpaid request always gets the
402challenge, whatever its parameters, so agents and catalog probes can read the price first. Parameters are validated after the payment is verified and before any data is produced: a malformed paid request gets400and the payment is never settled. Paid handlers serve from stored data and refresh from the source when it is older than 45 seconds; player statistics are read from the source on first request, stored, and refreshed after six hours (closed seasons never change). - Payment layer. The official x402 SDK produces the 402 challenge, verifies the payment through a facilitator and settles it only after the handler has succeeded.
4. Data model
Canonical events
Event ids are stable and sport-prefixed: fb-<id> for football, bb-<id> for basketball. Each event carries competition, season, home and away teams (id and name), score, half-time score, red cards, kickoff time and a normalized status:
scheduled · live · halftime · finished · finished_aet · finished_pen · postponed · awarded
Response envelope
{
"data": { ... },
"meta": { "sourceTimestamp": "...", "servedAt": "...", "freshnessSeconds": 11, "stale": false },
"proof": { "algorithm": "ed25519-sha256-jcs", "contentHash": "...", "signature": "...", "keyId": "...", "signedAt": "..." },
"anchor": { "status": "anchored", "merkleRoot": "...", "merkleProof": [...], "network": "...", "txId": "...", "round": 0 } // final results only
}
meta.freshnessSeconds is the age of the underlying data at serving time; meta.stale is true when the source could not be refreshed and the last stored data was served instead.
Endpoints and prices
| Endpoint | Content | USDC |
|---|---|---|
/v1/{football,basketball}/live | Events in play | 0.005 |
/v1/{football,basketball}/results | Events by date, competition, team, status; historical dates supported | 0.002 |
/v1/{football,basketball}/events/:eventId | Single event; football adds goals, assists, cards, substitutions, lineups | 0.002 |
/v1/{football,basketball}/events/:eventId/odds | Betting markets with outcomes and prices | 0.005 |
/v1/events/changes | Changes since a cursor or ISO time, with the next cursor | 0.001 |
/v1/results/final | Finalized results across both sports, with anchor data | 0.002 |
/v1/football/players/:playerId | Football player profile, career by season and one season match by match (goals, assists, cards, minutes) | 0.05 |
Lists are paginated (limit ≤ 200, opaque cursor). Prices are configuration and may change; the authoritative price is always the one in the 402 response.
5. Payments with x402 on Algorand
- The agent sends a normal
GET. - The server replies
402with aPAYMENT-REQUIREDheader: x402 version 2, schemeexact, network (Algorand), asset (USDC, ASA31566704on MainNet,10458941on TestNet), amount in base units, recipient, and the Bazaar extension. - The agent signs an Algorand transfer for that exact amount and repeats the request with the payment attached.
- The server asks the facilitator to verify the payment, runs the handler, and only if the handler returns a successful response asks the facilitator to settle. If the data cannot be produced (for example the source is down or the event does not exist), the payment is never settled and the agent pays nothing.
The facilitator used today is the GoPlausible facilitator, which supports x402 V2 on Algorand and co-signs network fees, so the buyer pays only the asset amount. The facilitator and discovery provider are configuration, not code: KocAlgo is not bound to a single operator.
6. Discovery through the x402 Bazaar
Every paid endpoint declares the official Bazaar discovery extension: HTTP method, input schema (query and path parameters), output schema and a realistic example, plus a description written for machines (sport, live or final, freshness, inputs, output, price, asset, network, and how to verify). Dynamic routes are published as templates (/v1/football/events/:eventId), so the catalog holds one entry per endpoint, not one per match.
A Bazaar catalog lists a resource after the first settled payment whose payload carries the extension. KocAlgo's publication tool performs exactly that: one real payment from a dedicated buyer wallet, followed by a check that the catalog entry matches our configuration (URL, method, version, scheme, network, asset, price, description and schemas). A scheduled audit then checks, without paying, that every resource is still listed and correct.
7. Verifiability: signatures and on-chain anchoring
Signed responses
- The
dataobject is serialized with the JSON Canonicalization Scheme (RFC 8785). contentHash= SHA-256 of those bytes.- The server signs the canonical form of
{algorithm, contentHash, keyId, signedAt}with its Ed25519 key.keyIdis the first 16 hex characters of the public key. - Public keys are served at
/.well-known/sports-data-keys.json. Ed25519 is also Algorand's signature scheme, so the same check can be done with Algorand tooling or on-chain.
A consumer recomputes the hash from the data it received, checks it against contentHash, and verifies the signature with the published key. Any modification of the data breaks the check.
Merkle anchoring of final results
Every hour, the hashes of results finalized since the last batch become leaves of a Merkle tree (leaf = SHA-256(0x00 ‖ contentHash), inner node = SHA-256(0x01 ‖ left ‖ right)). The root is written to Algorand in the note of a zero-amount transaction from a dedicated anchoring account, with the note sportsdata:v1:merkle:<root>. Responses for finalized results include the Merkle proof, transaction id and round, or anchor.status = "pending" until the next batch. One transaction per hour covers any number of results.
This proves that a given result existed in this exact form no later than the anchoring round. It does not prove that the underlying sporting fact is correct; it proves what we published and when.
8. Access: no token requirement until 31 December 2026
Until 31 December 2026 the x402 payment is the only access condition on both networks: any wallet that pays the quoted USDC amount receives the data. There is no account, API key or token-holding rule.
At the MainNet launch, a holding requirement applied: the paying wallet had to hold at least 1 KC (Algorand Standard Asset 1035899249). It was removed on 4 October 2026 so that new agents can start without an onboarding step. It returns on MainNet on 1 January 2027 00:00 (Europe/Istanbul): from then on, after the payment is verified, the payer must hold at least 1 KC; otherwise the request is rejected with kc_holding_required and the payment is never settled. From that date the requirement is also stated in every 402 description. TestNet has no holding requirement.
Payments are settled only when a request succeeds; an invalid parameter, an unknown id or a source outage returns an error without charge.
Browser-based x402 clients are supported: the API enables CORS for its public paths and exposes the PAYMENT-REQUIRED and PAYMENT-RESPONSE headers, and answers the preflight for PAYMENT-SIGNATURE.
9. Service levels and operations
| Objective (30-day window) | Target |
|---|---|
| Availability of paid endpoints (non-5xx responses) | ≥ 99% |
| Server time for paid requests from stored data, p95 (payment verification excluded) | ≤ 300 ms |
| Live data freshness, p95 | ≤ 60 s |
| Resources listed in the discovery catalog | All paid endpoints |
Pre-launch measurements on TestNet infrastructure: p95 server time 33 ms over 300 paid requests, p95 live freshness 41 s over three minutes of sampling. A watchdog samples health, freshness, error rate and latency every five minutes and stores the samples for SLO reporting. Deployments are immutable releases with an automatic rollback when the post-deployment check fails. Every response carries an X-Request-Id for support.
10. Limitations and risks
- Data source. Data is normalized from public sports sources that do not offer an official API. KocAlgo is not affiliated with any league, club or official data provider and does not claim a data licence. A change in a source's format can interrupt a feed; such rows are rejected and reported rather than served wrong.
- Correctness. Signatures and anchoring prove integrity and timing of what we publish, not the truth of the underlying event. Consumers settling high-value outcomes should combine sources.
- Single host. The service currently runs on a single machine behind a Cloudflare tunnel. A host outage makes the API unavailable; this is reflected in the 99% availability objective.
- Payment assets. Only USDC is accepted. The Algorand x402
exactscheme in the official SDK and the facilitator currently support asset transfers but not native ALGO payments. - Semantic search. The current facilitator lists catalog resources but does not offer the Bazaar
/discovery/searchendpoint. Agents find us by listing and filtering the catalog until search is available. - Player data. Player statistics come from the same public sources. Career lines do not include assists (assists are available per match), and per-match statistics such as shots or passes are not offered.
11. Roadmap
- Done: public TestNet and MainNet endpoints, with all 10 paid resources listed in the Bazaar catalog on both networks.
- Done (October 2026): football player statistics endpoint; CORS for browser-based x402 clients; KC holding requirement suspended until 31 December 2026.
- MCP tools (
get_live_football_matches,get_live_basketball_games,get_match_result,get_results_since,verify_match_result) published through the Bazaar MCP extension, sharing the same business logic as the HTTP API. - Native ALGO payments when supported by the SDK and facilitator.
- Semantic search verification when supported by the discovery provider.
12. Disclaimer
KocAlgo provides sports data for informational purposes. Odds data is informational and is not betting or financial advice. Service objectives are targets, not guarantees. Specifications in this document describe the system as of version 0.1 and may change; the 402 challenge and the published schemas are authoritative.