Version v1 · MLB Data · Season 2026-regular
The Fangorithm API is an extension of fangorithm.com. To get started, create an account and visit your account settings — an API key is generated for you automatically.
We also support the x402 protocol for pay-per-request access without an account. See the x402 section below for details.
This API is machine-discoverable. Point an agent at any of these:
All endpoints (except /health) require an API key via the X-API-Key header.
curl -H "X-API-Key: YOUR_KEY" https://api.fangorithm.com/v1/mlb/teams
We support the x402 protocol for pay-per-request access with stablecoins — no account or API key required. Requests are settled on-chain in USDC via an x402 facilitator.
| Network | Chain ID | Asset |
|---|---|---|
| Base mainnet | eip155:8453 | USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Solana mainnet | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp | USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
Prices are in USDC base units (6 decimals) — 1000 = $0.001, 5000 = $0.005.
| Route | Price |
|---|---|
/v1/mlb/players, /v1/mlb/players/:id | $0.001 |
/v1/mlb/players/:id/stats, /v1/mlb/players/:id/splits | $0.002 |
/v1/mlb/teams, /v1/mlb/teams/:id, /v1/mlb/teams/:id/roster | $0.001 |
/v1/mlb/teams/:id/stats, /v1/mlb/teams/:id/splits | $0.002 |
/v1/mlb/games, /v1/mlb/games/:id | $0.001 |
/v1/mlb/games/:id/boxscore, /v1/mlb/games/:id/play-by-play | $0.005 |
/v1/mlb/standings, /v1/mlb/park-factors, /v1/mlb/park-factors/:id, /v1/mlb/daily-matchups | $0.001 |
/v1/mlb/players/:id/game-logs | $0.005 |
Payments must settle within 60 seconds. x402 requests bypass the tiered rate limit — each call is paid individually.
1. Call an endpoint without an X-API-Key or PAYMENT-SIGNATURE header. The server responds with 402 Payment Required and a JSON body describing accepted payment options:
curl -i https://api.fangorithm.com/v1/mlb/players/12345/stats
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: <base64 of body>
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"maxAmountRequired": "2000",
"resource": "/v1/mlb/players/12345/stats",
"description": "Get MLB player season stats",
"payTo": "0x37459795E8f7B289c3cD646Ba92544a8EC433872",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"maxTimeoutSeconds": 60
},
{
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"maxAmountRequired": "2000",
"resource": "/v1/mlb/players/12345/stats",
"description": "Get MLB player season stats",
"payTo": "5C7ARtmtA2jVrgphoZocTacs7fa175frEVbWnGMGNtj3",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"maxTimeoutSeconds": 60
}
],
"error": "Payment required. Include a PAYMENT-SIGNATURE header or an X-API-Key header."
}
2. Sign a payment payload matching one of the accepts entries, base64-encode it, and retry the request with a PAYMENT-SIGNATURE header. On success, the response includes a PAYMENT-RESPONSE header with the settled transaction details.
The easiest integration uses the official x402-fetch library, which wraps fetch and handles the 402 challenge/retry automatically with a viem wallet.
import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);
const res = await fetchWithPayment(
"https://api.fangorithm.com/v1/mlb/games/20260615-LAD-SF/boxscore"
);
const data = await res.json();
console.log(data);
// Decode the settlement header if you want the on-chain tx
const settled = JSON.parse(atob(res.headers.get("PAYMENT-RESPONSE")));
console.log("Paid by:", settled.payer);
# 1) Get the challenge
curl -s https://api.fangorithm.com/v1/mlb/players/545361 | jq .
# 2) Build & sign a payment off-chain, base64 it, then:
curl -H "PAYMENT-SIGNATURE: $SIGNED_PAYLOAD_B64" \
https://api.fangorithm.com/v1/mlb/players/545361
402 with code PAYMENT_INVALID, unsupported networks return 400 with UNSUPPORTED_NETWORK, and facilitator outages return 502 with PAYMENT_VERIFICATION_FAILED or PAYMENT_SETTLEMENT_FAILED.All x402 payments settle to the addresses below. These are the same payTo values returned in the 402 challenge — always verify against the live response before signing.
| Network | Address |
|---|---|
| Base (EVM) | 0x37459795E8f7B289c3cD646Ba92544a8EC433872 |
| Solana | 5C7ARtmtA2jVrgphoZocTacs7fa175frEVbWnGMGNtj3 |
| Tier | Requests / minute |
|---|---|
| Free | 3 |
| Member | 100 |
Rate limit info is returned in the RateLimit-Limit response header.
| team | Filter by team abbreviation | ?team=NYY |
| position | Filter by position (comma-separated) | ?position=SS,2B |
| season | Season identifier | ?season=2026-regular |
| sort | Sort field and direction | ?sort=name:asc |
| limit | Results per page (max 200) | ?limit=25 |
| offset | Pagination offset | ?offset=50 |
| :id | MLB ID only — the player's mlb_id | /v1/mlb/players/660271/game-logs |
| season | Season identifier (current season only) | ?season=2026-regular |
| limit | Entries per page | ?limit=25 |
| offset | Pagination offset | ?offset=50 |
Entries are sorted ascending by game date and refreshed daily. Per-pitch at-bat detail is served by /v1/mlb/games/:id/play-by-play.
| sort | Sort field and direction | ?sort=name:asc |
| limit | Results per page | ?limit=25 |
| offset | Pagination offset | ?offset=10 |
| date | Required* Date in YYYYMMDD | ?date=20260615 |
| team | Required* Team abbreviation | ?team=LAD |
| status | Filter by status | ?status=COMPLETED |
| season | Season identifier | ?season=2026-regular |
* At least one of date or team is required.
Valid statuses: UNPLAYED, LIVE, COMPLETED, COMPLETED_PENDING_REVIEW
| season | Season identifier (current season only) | ?season=2026-regular |
| sort | Sort field and direction | ?sort=standings.winPct:desc |
| limit | Results per page | ?limit=15 |
| offset | Pagination offset | ?offset=15 |
Returns all 30 teams sorted by win percentage, each with standings (wins, losses, winPct, gamesBack, run differential) and record (streak, home/away/division/last-ten splits). Group by divisionId / conferenceId client-side. Refreshed daily.
| season | Season identifier | ?season=2026-regular |
| team | Filter by home-team abbreviation (comma-separated) | ?team=COL,BOS |
| sort | Sort field and direction | ?sort=parkFactors.runs:desc |
| limit | Results per page | ?limit=30 |
| offset | Pagination offset | ?offset=0 |
Factors are normalized indexes (100 = league average) for runs, hits, home runs, and more, alongside per-game counting stats. Refreshed daily.
| date | Date in YYYYMMDD — defaults to today (UTC); pass explicitly to avoid late-night UTC rollover | ?date=20260615 |
| team | Filter by team abbreviation (comma-separated, matches home or away) | ?team=LAD |
| sort | Sort field and direction | ?sort=gameTime:asc |
| limit | Results per page | ?limit=15 |
| offset | Pagination offset | ?offset=0 |
Each matchup includes venue, probable pitchers, and batting-order lineups with a lineupStatus of projected or official. Synced twice daily — official lineups land in the evening (UTC) refresh.
All responses return JSON with this structure:
{
"version": "v1",
"timestamp": "2026-06-15T12:00:00.000Z",
"data": { ... },
"meta": { "season": "2026-regular" },
"pagination": {
"total": 150,
"limit": 50,
"offset": 0,
"hasNext": true,
"hasPrev": false,
"nextOffset": 50,
"prevOffset": null
}
}
{
"version": "v1",
"timestamp": "...",
"error": {
"code": "NOT_FOUND",
"message": "Player not found."
}
}
| 400 | Bad request / invalid params |
| 401 | Missing or invalid API key |
| 404 | Resource not found |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
| INVALID_API_KEY | Key not recognized |
| RATE_LIMIT_EXCEEDED | Too many requests |
| FILTER_REQUIRED | Missing required filter |
| NOT_FOUND | Route or resource missing |