Required columns
Each row is one settled bet on an esports market. We compute fair value per row, compare to your offered line, and aggregate for the weekly report.
| Column | Type | Example | Notes |
|---|---|---|---|
| operator_event_id | str | thp-2026-9847 | Your internal event ID — opaque to us, used to deduplicate |
| sport | enum | cs2 | One of: cs2, dota, cod, rl |
| league_or_tournament | str | BLAST Premier Spring | Free text; helps us cross-reference our match DB |
| start_time_utc | ISO 8601 | 2026-04-22T18:00:00Z | Match scheduled start in UTC |
| team_1 | str | Vitality | Home / first team name; we fuzzy-match to our DB |
| team_2 | str | Natus Vincere | Away / second team name |
| market_type | enum | moneyline | One of: moneyline, spread, total, correct_score |
| selection | str | team_1 | For moneyline: team_1 or team_2.
For spread/total: include the line in the value (e.g. team_1_-1.5, over_2.5) |
| line_or_handicap | float? | -1.5 | Numeric handicap line for spread/total markets; null for moneyline |
| offered_decimal_odds | float | 1.85 | The decimal odds you offered at the moment of the bet |
| offered_timestamp_utc | ISO 8601 | 2026-04-22T17:42:11Z | When the bet was struck — used to align with our pre-event quote |
| settlement_result | enum | win | One of: win, lose, push, void |
| settlement_timestamp_utc | ISO 8601 | 2026-04-22T20:18:33Z | When the bet settled |
| void_flag | bool | false | True if the market was voided (we exclude these from leak metrics) |
Optional but valuable columns
Including these lets us produce stake-weighted metrics instead of unit-weighted. A 7pp pricing miss on a $20 bet is noise; a 3pp miss on a high-handle CS2 final is real money. Without these, the report is unweighted and we say so explicitly.
| Column | Type | Example | Notes |
|---|---|---|---|
| stake_or_exposure | float | 247.50 | Stake taken on this side, in your reporting currency |
| currency | str | USD | ISO 4217 currency code; needed if you mix currencies |
| closing_decimal_odds | float? | 1.78 | Your own closing line — lets us compute internal CLV in addition to fair-value comparison |
| vendor_name | str? | kambi-feed | Source of the offered line if not your own model |
| market_status | enum? | open | Open / suspended / closed at the time of the bet |
| internal_limit_tier | str? | tier_2 | Your customer's segmentation tier (anonymized) |
| customer_segment_anonymized | str? | recreational | Recreational / sharp / vip — DO NOT include actual customer IDs |
Privacy: we never want customer-identifiable data. No real
customer IDs, names, emails, IPs, or device fingerprints. Use opaque tier
labels only. See /pilot/data-handling.
Format
- UTF-8 encoded CSV
- Comma-delimited, double-quote text containing commas
- RFC 4180 line endings (
\r\n) preferred but\naccepted - One file per UTC day, named
{operator}_{YYYY-MM-DD}.csv(e.g.thunderpick_2026-04-29.csv) - Empty value = empty string (don't write "null" or "None")
Drop options
- S3 bucket — we'll provision a bucket with a unique IAM user and rotating access key. You drop daily; we pull. Cleanest for ops teams.
- SFTP — we provide a hostname + per-operator user/key
pair. Drop to
/incoming/; we sweep every 4 hours. - Email attachment — for the first week only. Send to
your assigned
pilot-{slug}@address. Attachments are auto-extracted to a private bucket and the email is deleted within 1 hour.
Validation
The first file you send is sanity-checked end-to-end before we generate your sample report. We email back within 24 hours with one of:
- Accepted — we matched ≥80% of rows to our match DB and will produce a report.
- Partial — we matched 50–79%. We send back a list of the team-name normalization issues so you can adjust the export.
- Rejected — we matched <50%. Almost always a column naming mismatch or a sport-code typo. We help fix it on a 30-min call.