Downstream Aggregator API
Multi-sport odds, scorecard, and live TV for white-label platforms. Responses are field-preserving (normalize: false).
https://korewhitelabelmall.xyz/365Alias:
https://korewhitelabelmall.xyz/api/365Sky alias (same APIs / event_id_sky):
https://korewhitelabelmall.xyz/sky · /api/skyLive buffer:
GET /365/socket/odds (poll 2–5s) — event freshness / scores snapshot, not full laddersOptional ticks:
wss://korewhitelabelmall.xyz/ws/odds (not a substitute for HTTP odds depth)Auth:
X-Aggregator-Key: <your-platform-key> on every partner call (this docs page is public).
Integration model
Your end users → YOUR backend / CDN / WS
↓ poll every 1–2s (focused) or 2–5s
Feed365 /365/{sport}/inplay → then /{eventId}/odds|/fancy|/bookmaker
Call Feed365 only from your server — never from mobile or browser clients. Use one backend poller per platform (shared cache for your users). Keys stay server-side; rotate with Kore ops if leaked.
Important: /inplay and /socket/odds list events (teams, live flags, scores). Prices live on event depth routes (/odds, /fancy, /bookmaker, /premium) or POST /odds/unified. Match odds use selections[].back_odds / lay_odds or runners[].back / lay — not fields on the inplay row.
Quick test
export FEED365_BASE=https://korewhitelabelmall.xyz/365
export FEED365_KEY='<your-platform-key>'
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/health"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/catalog"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/cricket/inplay"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/soccer/inplay"
# Pick a live eventId from inplay (prefer rows with marketType / _index.markets set — those have socket prices).
# match_id and exchange eventId both work on depth routes when the event is indexed.
EVENT_ID=$(curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/soccer/inplay" | jq -r '.data[] | select(.marketType!=null) | .eventId' | head -1)
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/soccer/$EVENT_ID/odds"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/soccer/$EVENT_ID/scorecard"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/soccer/$EVENT_ID/livetv"
curl -sS -X POST -H "X-Aggregator-Key: $FEED365_KEY" -H "Content-Type: application/json" \
"$FEED365_BASE/odds/unified" -d "{\"matchIds\":[\"$EVENT_ID\"]}"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" "$FEED365_BASE/socket/odds"
Healthy: status: "live", freshness.stale: false, ageSec typically low. If status: "stale", do not treat odds as live.
Market types
| Type | Route | Notes |
|---|---|---|
| Match odds / lines | GET …/odds → markets[] | marketId, marketType (e.g. MATCH_ODDS), runners[].back[{price,size}] / lay[] |
| Fancy | GET …/fancy (also nested on /odds) | Panel rows M,RN,RY,ON,OY,S,MI (may appear under markets[].raw) |
| Bookmaker | GET …/bookmaker | markets[].runners[].back/lay or raw B[] / SL[{I,B,L}] |
| Premium | GET …/premium, unified premium | Sportsbook markets + selection pricing |
| Catalog | GET /365/catalog, sport hubs | Sports, live counts, event lists |
Either match_id or exchange eventId is accepted on /odds, /fancy, /bookmaker, /premium, /scorecard, and /livetv.
Primary routes
| Method | Path | Purpose |
|---|---|---|
| GET | /365/health | Liveness + freshness |
| GET | /365/catalog | Sports + live counts |
| GET | /365/sports | Sport list |
| GET | /365/{sport} | Sport hub |
| GET | /365/{sport}/inplay | In-play events in data[] — each row includes marketType, marketTypes[], and _index.markets[] when socket-priced; catalog-only rows may have null/empty market types (check /odds ok) |
| GET | /365/{sport}/upcoming | Upcoming events — each row includes marketType, marketTypes[], and _index.markets[] |
| GET | /365/{sport}/allevents | All indexed events (same market-type fields as upcoming/inplay) |
| GET | /365/{sport}/{eventId} | Single event (wrong sport slug auto-corrects via sportCorrected) |
| GET | /365/{sport}/{eventId}/odds | Odds bundle |
| GET | /365/{sport}/{eventId}/scorecard | Live score / scorecard |
| GET | /365/{sport}/{eventId}/livetv | Live TV URL when available (ok: true only with a real stream) |
| GET | /365/{sport}/{eventId}/markets | Markets list |
| GET | /365/{sport}/{eventId}/fancy | Fancy markets |
| GET | /365/{sport}/{eventId}/bookmaker | Bookmaker markets |
| GET | /365/{sport}/{eventId}/premium | Premium sportsbook |
| POST | /365/odds/unified | Bulk odds — ok:true + data[] rows (market/fancy/bookmaker/premium/scores); see pricedCount |
| GET | /365/socket | Socket connection info for your backend |
| GET | /365/socket/odds | Buffered live snapshot (poll 2–5s) |
| GET | /365/search?q= | Event search |
| GET | /365/wallet | Partner balance / locked / ledger |
| POST | /365/wallet/credit | Top-up wallet |
| POST | /365/wallet/webhook | Register settlement callback URL |
| POST | /365/settlement/trace | Register bet → settlementId |
| GET | /365/settlement/{settlementId} | Poll settlement result |
| GET | /365/settlement | List your traces |
| POST | /365/settlement/{settlementId}/refresh | Force re-resolve |
| POST | /365/settlement/{settlementId}/result | Manual close (won/lost/void/push) |
| WS | wss://korewhitelabelmall.xyz/ws/odds | Optional live-wire ticks; use HTTP for full market depth |
Identifiers
| Field | Meaning |
|---|---|
eventId | Event key — match_id or exchange id (both accepted on depth routes) |
marketType | e.g. MATCH_ODDS, WIN, PLACE |
marketId | Exchange market id when present |
runners[] | Selections; ladders as BO / LO when present |
_index | Feed365 routing helper |
Live data & TV
- Poll
GET /365/socket/oddsfor the live buffer; refresh event/odds,/fancy,/bookmaker,/premium,/scorecardon demand. - Use live data only when
freshness.stale === false. - Live paths send
Cache-Control: no-store— always revalidate. /livetvreturnsok: trueonly with a real stream URL. No TV →ok: false(never a fake demo URL).
Partner wallet + settlement
Use GET /365/wallet. With stake on POST /settlement/trace, stake is debited/locked; on won / lost / void / push the wallet settles automatically and responses include needsLocalClose: true — close your local bet too. Optional webhook: POST /365/wallet/webhook.
marketKind: match_odds | fancy | bookmaker | other. Requires selectionId or selectionName. Fancy may also need line / runs / sessionKey. Same open betId is idempotent. Create freezes an event snapshot (homeName/awayName/eventName/…) so settle still works after the panel event leaves (EVENT_NOT_FOUND).
Hugging Face auto-settle (API host): FEED365_HF_OUTCOME=1 + FEED365_HF_AUTO_DECLARE=1 (defaults on). Collects snapshot + scorecard leftovers + public boards, then HF Inference (HF_TOKEN, model FEED365_HF_INFERENCE_MODEL default Qwen/Qwen2.5-1.5B-Instruct) extracts structured result + confidence. Auto-declares when confidence >= FEED365_HF_MIN_CONFIDENCE (default 0.75). Match-odds → won/lost/void; fancy/line only with high-confidence line/result_runs — else stays open. Response: hfState (pending_hf|resolved|unresolvable|unknown), outcomeSource (huggingface|public_board+hf), hfConfidence, hfModelId, hfEvidenceSnippet, hfAttempts, always needsLocalClose: true on declare. After FEED365_HF_MAX_ATTEMPTS → unresolvable (keep open; auto-void only if FEED365_HF_AUTO_VOID_UNRESOLVABLE=1). In-API retry interval: FEED365_HF_AUTO_REFRESH_MS. Historical Hub datasets never invent live results unless FEED365_HF_DATASET_ALLOW_DECLARE=1. Markdown details: GET /api/settlement-trace/docs. Batch: scripts/hf/feed365-batch-settle.py.
Recovery: unknown id → 404 SETTLEMENT_NOT_FOUND with recovery hints. Evicted closed id → 410 orphan_recoverable + outcome. Lookup: GET /365/settlement?betId=. Manual close may include betId in the body if settlementId was lost.
curl -sS -X POST -H "X-Aggregator-Key: $FEED365_KEY" -H "Content-Type: application/json" \
"$FEED365_BASE/settlement/trace" -d '{
"betId": "partner-bet-123",
"sport": "cricket",
"eventId": "35830529",
"marketType": "MATCH_ODDS",
"marketKind": "match_odds",
"selectionName": "England",
"homeName": "England",
"awayName": "India",
"side": "back",
"odds": 1.5,
"stake": 10
}'
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" \
"$FEED365_BASE/settlement/<settlementId>"
curl -sS -H "X-Aggregator-Key: $FEED365_KEY" \
"$FEED365_BASE/settlement?betId=partner-bet-123"
curl -sS -X POST -H "X-Aggregator-Key: $FEED365_KEY" -H "Content-Type: application/json" \
"$FEED365_BASE/settlement/<settlementId>/result" -d '{"status":"won","resultNote":"manual"}'
Sport slugs
soccer, tennis, cricket, horse_racing, greyhound_racing, basketball, baseball, ice_hockey, american_football, mma, darts, snooker, golf, boxing, volleyball, table_tennis, …
Aliases: football → soccer · horseracing → horse_racing · nfl → american_football · dogs → greyhound_racing
Backend env (your platform)
FEED365_BASE=https://korewhitelabelmall.xyz/365 FEED365_KEY=<your-platform-key> FEED365_WS=wss://korewhitelabelmall.xyz/ws/odds FEED365_POLL_MS=2000
Example request
GET /365/soccer/inplay HTTP/1.1 Host: korewhitelabelmall.xyz X-Aggregator-Key: <your-platform-key> Accept: application/json
Platform keys are issued by Kore. Keep them on your backend only. Do not embed keys in apps or public frontends.