Documentation / Start here
Webhooks
Final scores and finished periods posted to your server as they happen.
What is sent
| Event | When | Plans |
|---|---|---|
game.final | A game has its final score. | Live and up |
game.period | A 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 realgame.finalnow, 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.