/** * /api/futures/:sport (Wave 2A, D1) — championship/outright futures. * * Response contract: * { sport, updated_at, markets: [{ key, title, selections: * [{ name, price, prevPrice?, move? }] }] } * No data / gated-off (FUTURES_ENABLED=0) / quota-skip → { sport, updated_at, * markets: [] }. Never errors, never fabricates a price. * * QUOTA-DISCIPLINED: futuresService fetches at most one odds-api outrights call * per sport per 12h (default), isolated from the daily player-prop budget. */ const express = require('express'); const { createRateLimit } = require('../middleware/rateLimit'); const router = express.Router(); // Public throttle (30/min — futures are cheap to serve from cache). router.use(createRateLimit({ windowMs: 60_000, max: 30 })); const MISSION_HEADER = { 'X-VYNDR-Mission': 'The slate is never empty' }; router.get('/:sport', async (req, res) => { const sport = String(req.params.sport || '').toLowerCase(); try { const { getFutures } = require('../services/futuresService'); const payload = await getFutures(sport); res.set('Cache-Control', 'public, max-age=600'); return res.set(MISSION_HEADER).json(payload); } catch (err) { console.error('[futures]', err.message); return res.set(MISSION_HEADER).json({ sport, updated_at: new Date().toISOString(), markets: [] }); } }); module.exports = router;