590 lines
14 KiB
YAML
590 lines
14 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Hermes API
|
|
version: 0.1.0
|
|
description: Native betting study prototype API.
|
|
servers:
|
|
- url: http://localhost:3000
|
|
paths:
|
|
/health:
|
|
get:
|
|
summary: Health check
|
|
responses:
|
|
'200':
|
|
description: Service health
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HealthResponse'
|
|
/api/v1/session/start:
|
|
post:
|
|
summary: Start a session
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SessionStartRequest'
|
|
responses:
|
|
'201':
|
|
description: Session started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SessionResponse'
|
|
/api/v1/session/end:
|
|
post:
|
|
summary: End the current session
|
|
responses:
|
|
'200':
|
|
description: Session ended
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SessionResponse'
|
|
/api/v1/session/me:
|
|
get:
|
|
summary: Inspect the current session
|
|
responses:
|
|
'200':
|
|
description: Current session snapshot
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SessionResponse'
|
|
/api/v1/feed/next:
|
|
get:
|
|
summary: Fetch the next round
|
|
responses:
|
|
'200':
|
|
description: Next event payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Event'
|
|
/api/v1/events/{event_id}:
|
|
get:
|
|
summary: Fetch an event
|
|
parameters:
|
|
- name: event_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Event
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Event'
|
|
/api/v1/events/{event_id}/manifest:
|
|
get:
|
|
summary: Fetch the event manifest
|
|
parameters:
|
|
- name: event_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Manifest
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventManifest'
|
|
/api/v1/events/{event_id}/markets:
|
|
get:
|
|
summary: List markets for an event
|
|
parameters:
|
|
- name: event_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Markets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Market'
|
|
/api/v1/markets/{market_id}/odds/current:
|
|
get:
|
|
summary: Fetch current odds for a market
|
|
parameters:
|
|
- name: market_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Current odds
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OddsVersion'
|
|
/api/v1/stream:
|
|
get:
|
|
summary: Live odds and state stream
|
|
responses:
|
|
'200':
|
|
description: Server-sent events stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
/api/v1/bets/intent:
|
|
post:
|
|
summary: Submit a bet intent
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BetIntentRequest'
|
|
responses:
|
|
'201':
|
|
description: Bet intent result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BetIntentResponse'
|
|
/api/v1/bets/{bet_intent_id}:
|
|
get:
|
|
summary: Fetch a bet intent
|
|
parameters:
|
|
- name: bet_intent_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Bet intent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BetIntentResponse'
|
|
/api/v1/events/{event_id}/result:
|
|
get:
|
|
summary: Fetch event result
|
|
parameters:
|
|
- name: event_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: Result payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Settlement'
|
|
/api/v1/analytics/batch:
|
|
post:
|
|
summary: Ingest analytics batch
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AnalyticsBatchRequest'
|
|
responses:
|
|
'202':
|
|
description: Accepted
|
|
/api/v1/experiments/config:
|
|
get:
|
|
summary: Fetch experiment config
|
|
responses:
|
|
'200':
|
|
description: Experiment config
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ExperimentConfig'
|
|
/api/v1/localization/{locale_code}:
|
|
get:
|
|
summary: Fetch a localization bundle
|
|
parameters:
|
|
- name: locale_code
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
enum: [en, sv]
|
|
responses:
|
|
'200':
|
|
description: Localization bundle
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LocalizationBundle'
|
|
/api/v1/admin/events:
|
|
post:
|
|
summary: Create an event
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
/api/v1/admin/markets:
|
|
post:
|
|
summary: Create a market
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
/api/v1/admin/odds:
|
|
post:
|
|
summary: Publish odds
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
/api/v1/admin/settlements:
|
|
post:
|
|
summary: Publish a settlement
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
components:
|
|
schemas:
|
|
HealthResponse:
|
|
type: object
|
|
required: [status, service_name, environment, version, uptime_ms, server_time, database_ready, redis_ready]
|
|
properties:
|
|
status:
|
|
type: string
|
|
service_name:
|
|
type: string
|
|
environment:
|
|
type: string
|
|
version:
|
|
type: string
|
|
uptime_ms:
|
|
type: integer
|
|
server_time:
|
|
type: string
|
|
format: date-time
|
|
database_ready:
|
|
type: boolean
|
|
redis_ready:
|
|
type: boolean
|
|
SessionStartRequest:
|
|
type: object
|
|
properties:
|
|
external_ref:
|
|
type: string
|
|
locale_code:
|
|
type: string
|
|
device_platform:
|
|
type: string
|
|
device_model:
|
|
type: string
|
|
os_version:
|
|
type: string
|
|
app_version:
|
|
type: string
|
|
SessionResponse:
|
|
type: object
|
|
required: [session_id, user_id, started_at, experiment_variant, app_version, locale_code, device_platform]
|
|
properties:
|
|
session_id:
|
|
type: string
|
|
format: uuid
|
|
user_id:
|
|
type: string
|
|
format: uuid
|
|
started_at:
|
|
type: string
|
|
format: date-time
|
|
ended_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
experiment_variant:
|
|
type: string
|
|
app_version:
|
|
type: string
|
|
device_model:
|
|
type: string
|
|
nullable: true
|
|
os_version:
|
|
type: string
|
|
nullable: true
|
|
locale_code:
|
|
type: string
|
|
device_platform:
|
|
type: string
|
|
Event:
|
|
type: object
|
|
required: [id, sport_type, source_ref, title_en, title_sv, status, lock_at, settle_at]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
sport_type:
|
|
type: string
|
|
source_ref:
|
|
type: string
|
|
title_en:
|
|
type: string
|
|
title_sv:
|
|
type: string
|
|
status:
|
|
type: string
|
|
preview_start_ms:
|
|
type: integer
|
|
preview_end_ms:
|
|
type: integer
|
|
reveal_start_ms:
|
|
type: integer
|
|
reveal_end_ms:
|
|
type: integer
|
|
lock_at:
|
|
type: string
|
|
format: date-time
|
|
settle_at:
|
|
type: string
|
|
format: date-time
|
|
EventManifest:
|
|
type: object
|
|
properties:
|
|
event:
|
|
$ref: '#/components/schemas/Event'
|
|
media:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/EventMedia'
|
|
markets:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Market'
|
|
EventMedia:
|
|
type: object
|
|
required: [id, event_id, media_type, hls_master_url, duration_ms]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
event_id:
|
|
type: string
|
|
format: uuid
|
|
media_type:
|
|
type: string
|
|
hls_master_url:
|
|
type: string
|
|
poster_url:
|
|
type: string
|
|
nullable: true
|
|
duration_ms:
|
|
type: integer
|
|
preview_start_ms:
|
|
type: integer
|
|
preview_end_ms:
|
|
type: integer
|
|
reveal_start_ms:
|
|
type: integer
|
|
reveal_end_ms:
|
|
type: integer
|
|
Market:
|
|
type: object
|
|
required: [id, event_id, question_key, market_type, status, lock_at, settlement_rule_key]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
event_id:
|
|
type: string
|
|
format: uuid
|
|
question_key:
|
|
type: string
|
|
market_type:
|
|
type: string
|
|
status:
|
|
type: string
|
|
lock_at:
|
|
type: string
|
|
format: date-time
|
|
settlement_rule_key:
|
|
type: string
|
|
outcomes:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Outcome'
|
|
Outcome:
|
|
type: object
|
|
required: [id, market_id, outcome_code, label_key, sort_order]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
market_id:
|
|
type: string
|
|
format: uuid
|
|
outcome_code:
|
|
type: string
|
|
label_key:
|
|
type: string
|
|
sort_order:
|
|
type: integer
|
|
OddsVersion:
|
|
type: object
|
|
required: [id, market_id, version_no, created_at, is_current]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
market_id:
|
|
type: string
|
|
format: uuid
|
|
version_no:
|
|
type: integer
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
is_current:
|
|
type: boolean
|
|
odds:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OutcomeOdds'
|
|
OutcomeOdds:
|
|
type: object
|
|
required: [id, odds_version_id, outcome_id, decimal_odds, fractional_num, fractional_den]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
odds_version_id:
|
|
type: string
|
|
format: uuid
|
|
outcome_id:
|
|
type: string
|
|
format: uuid
|
|
decimal_odds:
|
|
type: number
|
|
fractional_num:
|
|
type: integer
|
|
fractional_den:
|
|
type: integer
|
|
BetIntentRequest:
|
|
type: object
|
|
required: [session_id, event_id, market_id, outcome_id, idempotency_key, client_sent_at]
|
|
properties:
|
|
session_id:
|
|
type: string
|
|
format: uuid
|
|
event_id:
|
|
type: string
|
|
format: uuid
|
|
market_id:
|
|
type: string
|
|
format: uuid
|
|
outcome_id:
|
|
type: string
|
|
format: uuid
|
|
idempotency_key:
|
|
type: string
|
|
client_sent_at:
|
|
type: string
|
|
format: date-time
|
|
BetIntentResponse:
|
|
type: object
|
|
required: [id, accepted, acceptance_code, server_received_at]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
accepted:
|
|
type: boolean
|
|
acceptance_code:
|
|
type: string
|
|
accepted_odds_version_id:
|
|
type: string
|
|
format: uuid
|
|
nullable: true
|
|
server_received_at:
|
|
type: string
|
|
format: date-time
|
|
Settlement:
|
|
type: object
|
|
required: [id, market_id, settled_at, winning_outcome_id]
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
market_id:
|
|
type: string
|
|
format: uuid
|
|
settled_at:
|
|
type: string
|
|
format: date-time
|
|
winning_outcome_id:
|
|
type: string
|
|
format: uuid
|
|
AnalyticsBatchRequest:
|
|
type: object
|
|
required: [events]
|
|
properties:
|
|
events:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AnalyticsEventInput'
|
|
AnalyticsEventInput:
|
|
type: object
|
|
required: [event_name, occurred_at]
|
|
properties:
|
|
event_name:
|
|
type: string
|
|
occurred_at:
|
|
type: string
|
|
format: date-time
|
|
attributes:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AttributeInput'
|
|
AttributeInput:
|
|
type: object
|
|
required: [key, value]
|
|
properties:
|
|
key:
|
|
type: string
|
|
value:
|
|
type: string
|
|
ExperimentConfig:
|
|
type: object
|
|
properties:
|
|
variant:
|
|
type: string
|
|
feature_flags:
|
|
type: object
|
|
additionalProperties:
|
|
type: boolean
|
|
LocalizationBundle:
|
|
type: object
|
|
required: [locale_code, values]
|
|
properties:
|
|
locale_code:
|
|
type: string
|
|
values:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
ErrorResponse:
|
|
type: object
|
|
required: [code, message]
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|