basketballapi.net

Documentation / Start here

Webhooks

Final scores and finished periods posted to your server as they happen.

What is sent

EventWhenPlans
game.finalA game has its final score.Live and up
game.periodA period of a game in progress has ended.Live and up

Each event is one POST of JSON to your address, at most a minute or two after it happens. The body is the same shape for every event:

{
  "id": "evt_5c1f0a9e2b7d4c18",
  "type": "game.final",
  "created_at": "2026-10-01T20:47:12Z",
  "data": { "game": { "id": "gm_tawfgjqt", "home_score": 82, "away_score": 78, ... } }
}

Add a webhook

curl -X POST https://api.basketballapi.net/v1/webhooks \
  -H "Authorization: Bearer bba_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://you.example/hooks/basketball", "events": ["game.final", "game.period"]}'

Leave out events for all of them, and add competitions, a list of competition ids, to hear about those only. The answer carries the webhook's secret, once: keep it to check signatures. An account holds up to 10 webhooks.

  • GET /v1/webhooks: your webhooks, with the last 24 hours of deliveries.
  • POST /v1/webhooks/{id}/test: send the newest real game.final now, marked "test": true, and see what your server answered.
  • DELETE /v1/webhooks/{id}: remove one.

Check the signature

Every request carries X-BBA-Signature: t=1759351632,v1=5f2b...: the time it was sent and an HMAC-SHA256, with your secret, of the time, a dot and the raw body. Check it, and refuse a time more than five minutes old.

import hmac, hashlib, time

def verify(secret, header, body):
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    want = hmac.new(secret.encode(), (parts["t"] + "." + body).encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, parts["v1"])

The request also carries X-BBA-Event and X-BBA-Delivery, the event id, which stays the same on a retry: use it to skip one you have already handled.

Answering and retries

Answer with any 2xx status within 10 seconds. A timeout, a 5xx, a 408 or a 429 is tried again, 8 tries in all over about three days. Any other 4xx tells us not to: that delivery stops there. A webhook whose deliveries fail 20 times in a row is turned off and we email you; add it again once your server answers.

Addresses must be https on port 443 and reachable from the internet; redirects are not followed.