Skip to content
OFF SZN Network
Boys HoopsGirls HoopsBETAFootballBETA
LoginJOIN NOW
OFF SZN Hoops
HomeNewsRankingsDatabaseScoresEventsHigh SchoolsForums
Ctrl K
OFF SZN Hoops

High school basketball recruiting, rankings, and commitments — every state, every class.

Explore

  • Rankings
  • Recruiting Classes
  • Recruiter Rankings
  • Commitments
  • Commit Trends
  • Rankings Movers
  • Scores
  • News
  • Forums
  • Submit a Tip
  • Events
  • Film Room
  • Football
  • Girls Hoops
  • Almanac
  • Leaders
  • Saved Articles

Company

  • About
  • For Coaches
  • What's New
  • Coverage
  • Methodology
  • Pricing
  • FAQ
  • Contact
  • Install App
  • API & Embeds
The Daily Top 10

10 recruiting stories. Every morning. 7am.

Free forever. Unsubscribe anytime.

Got a scoop?
tips@offsznnetwork.com

Coverage by State

ArizonaLIVECaliforniaLIVE+ 49 more · expanding nationwide →
PrivacyData RightsExportAccount DeletionCookiesYouth safetyTermsCommunity GuidelinesDMCAAccessibilityCorrectionsPressSitemapRSS

© 2026 OFF SZN Network. All rights reserved.

Coast to coast

HomeRankingsNewsCommitsSign in
  1. Home
  2. Developers
Developers

OFF SZN API & Embeds

Free, read-only JSON API and iframable widgets for OFF SZN player profiles, composite rankings, commitments, news, and more. No API key required for the free tier. Attribution required. Versioned at /api/v1.

Rate limit
60 req/min/IP
JSON free tier · no key
Endpoints
14 GET routes
Stable under /api/v1
CORS
Enabled (*)
Browser fetch from any origin

Limits & honesty

  • Free tier: 60 requests / minute / IP for JSON routes. PDF is capped at 30 / min / IP. Exceeding returns 429 with code: rate_limited, a Retry-After header, and retryAfter (seconds) in the body.
  • No key required today. A future partner key header (X-OFFSZN-API-Key) is reserved; free tier ignores it.
  • Public card fields only — no scout bios, internal notes, or PII. Responses use explicit field allowlists.
  • Pagination: limit defaults to 25 (max 100 on most routes); offset is capped at 10,000.
  • Caching: successful responses are CDN-cached (~5 min). Error responses are never edge-cached.
  • Coverage: rankings and player depth vary by state and class year. Empty lists are valid JSON with total: 0, not 404s.

Endpoint catalog

MethodPathDescriptionQuery
GET/api/v1/playersList players (card fields)state, classYear, position, school, q, limit, offset
GET/api/v1/players/:idSingle player + composite ranks—
GET/api/v1/players/:id/timelineRecruiting timeline eventslimit
GET/api/v1/players/:id/articlesNews tagged to a player—
GET/api/v1/players/:id/pdfOne-pager PDF (binary; 30/min)—
GET/api/v1/rankingsComposite rankings feedstate, classYear, position, limit, offset
GET/api/v1/commitmentsLatest commitmentsstate, classYear, limit, offset
GET/api/v1/newsPublished headlines + summariesstate, category, q, limit, offset
GET/api/v1/eventsTournaments / events windowstate, from, to, limit, offset
GET/api/v1/collegesColleges by commit volumeq, limit, offset
GET/api/v1/scoresHS contest scores (AZ-sourced)gender, classification, status, limit, offset
GET/api/v1/team-rankingsProgram recruiting class rankssport, classYear, state, gender, sortBy, limit, offset
GET/api/v1/transfer-portalPortal entriessport, status, limit, offset
GET/api/v1/alumniGraduated / alumni prospectsstate, classYear, limit, offset

Detailed examples

GET/api/v1/players/:id

Fetch a single player profile + their composite ranking. Public card fields only.

Try it
https://offsznhoops.com/api/v1/players/cmo9lw9p00001jw047ke18g3e
Sample response
{
  "apiVersion": "v1",
  "data": {
    "id": "cmo9lw9p00001jw047ke18g3e",
    "firstName": "Jaden",
    "lastName": "Smith",
    "position": "SG",
    "classYear": 2027,
    "starRating": 5,
    "state": "AZ",
    "composite": {
      "compositeRating": 0.985,
      "nationalRank": 12,
      "positionRank": 3,
      "stateRank": 1
    },
    "url": "https://offsznhoops.com/players/cmo9lw9p00001jw047ke18g3e",
    "attribution": "Data via OFF SZN Hoops · offsznhoops.com"
  }
}
GET/api/v1/rankings

List rankings, filterable by state, classYear, and position. Paginated via offset.

ParamDescription
state2-letter code, e.g. AZ
classYearClass year, e.g. 2027
positionPG, SG, SF, PF, C
limit1–100 (default 25)
offsetPagination offset (max 10_000)
Try it
https://offsznhoops.com/api/v1/rankings?state=AZ&classYear=2027&limit=25
Sample response
{
  "apiVersion": "v1",
  "filters": { "state": "AZ", "classYear": 2027, "position": null },
  "pagination": { "offset": 0, "limit": 25, "total": 87 },
  "data": [
    {
      "rank": 12,
      "positionRank": 3,
      "stateRank": 1,
      "composite": 0.985,
      "player": {
        "id": "cmo9lw9p00001jw047ke18g3e",
        "firstName": "Jaden",
        "lastName": "Smith",
        "starRating": 5,
        "position": "SG",
        "classYear": 2027,
        "state": "AZ",
        "url": "https://offsznhoops.com/players/cmo9lw9p00001jw047ke18g3e"
      }
    }
  ],
  "attribution": "Data via OFF SZN Hoops · offsznhoops.com"
}
GET/api/v1/commitments

Latest commitments (event-sourced). Estimated import dates surface as null date + isDateEstimated: true.

ParamDescription
state2-letter code
classYearClass year filter
limit1–100 (default 25)
offsetPagination offset
Try it
https://offsznhoops.com/api/v1/commitments?state=AZ&limit=10
Sample response
{
  "apiVersion": "v1",
  "total": 42,
  "limit": 10,
  "offset": 0,
  "data": [
    {
      "id": "ev_…",
      "date": "2026-04-12T00:00:00.000Z",
      "isDateEstimated": false,
      "college": "Arizona",
      "player": { "id": "cmo9lw9p00001jw047ke18g3e", "firstName": "Jaden", "lastName": "Smith", "url": "…" }
    }
  ],
  "attribution": "OFF SZN Hoops · offsznhoops.com"
}

curl examples

Player by id
curl -sS "https://offsznhoops.com/api/v1/players/cmo9lw9p00001jw047ke18g3e"
Rankings slice
curl -sS "https://offsznhoops.com/api/v1/rankings?state=AZ&classYear=2027&limit=10"

Error responses

Errors share a stable JSON envelope on every /api/v1/* route (including PDF). The human string is always in error; structured clients should branch on code. Every error includes apiVersion, docs (/developers), CORS *, and Cache-Control: private, no-store so failures are never edge-cached.

StatuscodeWhen
404not_foundUnknown player id (or other missing resource)
404invalid_idMalformed id — use the id from list/rankings feeds
403LICENSE_MODULE_DISABLEDWhite-label install without the api_v1 module · may include module + tier
429rate_limitedOver free-tier budget (JSON 60/min · PDF 30/min) · Retry-After header + retryAfter body (seconds)
503unavailableTransient backend fault · retry with backoff
404 sample
{
  "apiVersion": "v1",
  "error": "Player not found. Confirm the id via GET /api/v1/players or GET /api/v1/rankings.",
  "code": "not_found",
  "docs": "/developers"
}
429 sample
{
  "apiVersion": "v1",
  "error": "Rate limited. Free tier is 60 req/min.",
  "code": "rate_limited",
  "docs": "/developers",
  "retryAfter": 13
}

No secrets in responses. Errors never include stack traces, env values, or internal query details. Empty list results are 200 with total: 0, not errors.

Embed widgets

Drop an iframe into any article. Widgets are noindex, carry attribution in the footer, and open profile links with target=_top so readers leave the iframe cleanly. Free-tier JSON under /api/v1/* is 60 req/min/IP (see Limits above); embed HTML pages are edge-cached (~5 min ISR) and are not the same rate-limit bucket.

Copy-paste snippets

Paste into CMS HTML or a static page. Attribution footer is built into each widget — do not strip the chrome.

Rankings /embed/rankings?state=AZ&classYear=2027
<iframe
  src="https://offsznhoops.com/embed/rankings?state=AZ&classYear=2027"
  width="100%"
  height="520"
  style="border:0;max-width:100%"
  loading="lazy"
  title="OFF SZN rankings"
></iframe>
Commitments /embed/commitments?state=AZ
<iframe
  src="https://offsznhoops.com/embed/commitments?state=AZ"
  width="100%"
  height="520"
  style="border:0;max-width:100%"
  loading="lazy"
  title="OFF SZN commitments"
></iframe>
Player card (live sample id) /embed/player/cmo9lw9p00001jw047ke18g3e
<iframe
  src="https://offsznhoops.com/embed/player/cmo9lw9p00001jw047ke18g3e"
  width="100%"
  height="320"
  style="border:0;max-width:560px"
  loading="lazy"
  title="OFF SZN player card"
></iframe>

Empty & error contract

  • Empty scope (true zero): compact frame with an Open full site CTA — never demo rankings, commits, or player cards.
  • Load failure:says temporarily unavailable (not “no data yet”) and still offers Retry + open full site.
  • Player embeds: require a real player id from GET /api/v1/rankings or GET /api/v1/players — sample below uses live id cmo9lw9p00001jw047ke18g3e (refreshed hourly).
  • API rate limit: free JSON tier is 60 requests / minute / IP (429 + code: rate_limited). PDF is 30/min. Embeds are HTML, not that JSON bucket.
GET/embed/rankings

Top-N rankings table. Omit state (or use ALL) for national. limit 5–25 (default 10). Empty filters show an open-site CTA — no invented rows.

Try it
https://offsznhoops.com/embed/rankings?state=AZ&classYear=2027
Embed code
<iframe
  src="https://offsznhoops.com/embed/rankings?state=AZ&classYear=2027"
  width="100%"
  height="520"
  style="border:0;max-width:100%"
  loading="lazy"
  title="OFF SZN rankings"
></iframe>
GET/embed/commitments

Latest commitments ticker. state optional; limit 5–25. Estimated import dates never display as real commit days.

Try it
https://offsznhoops.com/embed/commitments?state=AZ
Embed code
<iframe
  src="https://offsznhoops.com/embed/commitments?state=AZ"
  width="100%"
  height="520"
  style="border:0;max-width:100%"
  loading="lazy"
  title="OFF SZN commitments"
></iframe>
GET/embed/player/:id

Single-player card for articles and newsletters. height ~320 works well. Example id is a live top-ranked player (refreshed hourly).

Try it
https://offsznhoops.com/embed/player/cmo9lw9p00001jw047ke18g3e
Embed code
<iframe
  src="https://offsznhoops.com/embed/player/cmo9lw9p00001jw047ke18g3e"
  width="100%"
  height="320"
  style="border:0;max-width:560px"
  loading="lazy"
  title="OFF SZN player card"
></iframe>

Attribution

Free tier requires a visible attribution link to offsznhoops.com on the page or article using our data. API responses include an attribution string you can render verbatim. Embed widgets carry attribution natively.

Partner / commercial use

The free tier is public and no-key. It is rate-limited and attribution-required. If you are redistributing data at product scale, need higher throughput, or want a named contact, reach out — free tier stays available either way.

  • Free-tier rate limits (honest): JSON routes under /api/v1/* are 60 requests / minute / IP (enforced in shared withV1). Player PDF is 30 / minute / IP. Over budget returns 429 with code: rate_limited, Retry-After, and retryAfter (seconds).
  • Embeds require attribution: iframes under /embed/* already show a footer credit. If you build a custom UI from the API, keep a visible link to offsznhoops.com (or render the response attribution string). Do not strip embed chrome or re-skin widgets to hide the source.
  • Commercial / higher limits: for elevated caps, bulk historical dumps, webhook delivery, or SLA-style access, email partners@offsznnetwork.com or hello@offsznnetwork.com. Include expected volume, use case, and contact name.
Contact partners →

No invented partner tiers on this page — we only document limits the free tier actually enforces today.

Share
Live336recruits tracked0commits this week0stories this week21.4kschools covered· updated today