AI Agent Task: Integrate Sport Line API
Purpose
This file is a technical assignment for an AI agent that must integrate Sport Line API into an existing client website, application, or backend service.
Study the project’s architecture, language, framework, coding conventions, and existing approach to external APIs. Implement the integration in the project’s established style. Do not replace its architecture, interface, or existing business logic unless necessary.
This assignment requires implementation and verification, not merely a description of a possible solution. If the user requests only advice or a plan, do not modify files without permission.
Required Reading Before Implementation
Before changing code, study the Sport Line API documentation in this directory.
You must read:
- Integration Guide.
- Quick Start.
- Authentication and Access.
- Core Concepts.
- The documentation for every method required by the integration.
- The relevant data models and the Field Reference.
Do not begin implementation using this assignment alone. Treat the SportAPI documentation as the primary source for URLs, parameters, fields, response formats, and data update rules.
If the documentation is missing or its links are unavailable, tell the user before
starting the integration and ask for the complete client-documentation directory.
Integration Goal
Create a secure server-side Sport Line API integration that can:
- Retrieve the current sports line navigation hierarchy.
- Display available Prematch and Live matches.
- Open detailed data for a selected match.
- Display the odds, statistics, and submatches actually returned by the API.
- Update data regularly at the permitted frequency.
- Correctly handle empty responses, access errors, and disappeared matches.
Core integration flow:
menu → events → event
Information Required Before Starting
Inspect the project and locate, or ask the user for:
- The Sport Line API base URL issued by the SportAPI manager.
- The API key, which must be stored in a protected environment variable.
- Required sports line types: Prematch, Live, or both.
- The response language enabled for the key.
- Sports included in the client’s subscription.
- Pages, components, or internal APIs that will use the data.
- Display requirements for matches, odds, and statistics.
- Whether esports data is required.
- Whether additional services are connected: Live 3D Tracker, video, results, or a betting system.
- Project requirements for caching, logging, tests, and error handling.
Do not ask the user to publish an active API key in a shared chat. Recommend adding it to the project’s secrets system or a local environment variable.
If required values are unavailable, prepare a secure integration with placeholders and report what is still needed. Do not invent a base URL, key, sport ID, tournament ID, or match ID.
To obtain access, the user contacts the SportAPI manager: @suport_sportapi.
Configuration
Use the configuration mechanism established by the project. Recommended variable names:
SPORTAPI_BASE_URL=https://YOUR_API_DOMAIN
SPORTAPI_PACKAGE_KEY=YOUR_API_KEY
SPORTAPI_LANGUAGE=en
Add a separate sports line type setting when required:
SPORTAPI_LINE_TYPE=live
Rules:
- never hard-code an active key in source code;
- never commit the key to Git;
- never pass the key in the URL;
- never expose the key in logs or interface messages;
- never send the key to a browser or mobile application;
- request Sport Line API through the client’s backend;
- validate required configuration when the application starts.
One key is intended for one project and one approved environment. It is bound to a server domain or IP address. Do not use a production key in another environment without approval from SportAPI.
Connection Method
Sport Line API is a REST API. WebSocket support is under development and must not be used in a production integration before its official release.
Every method uses HTTP GET.
Pass the API key in the header:
Package: YOUR_API_KEY
Also send:
Accept: application/json
First-request example:
curl --request GET \
--url 'https://YOUR_API_DOMAIN/v1/menu/live/en' \
--header 'Package: YOUR_API_KEY'
Create One Shared API Client
Do not duplicate HTTP logic in every method. Create one client or request function that:
- Accepts a relative method path.
- Adds the base URL.
- Sends the
PackageandAcceptheaders. - Sets reasonable connection and response timeouts.
- Parses JSON.
- Checks the HTTP status.
- Checks
error_codeanderror_message. - Validates the standard
status,page, andbodyenvelope. - Returns a typed or otherwise predictable result.
- Never exposes the key in an error.
Use the project’s standard HTTP library and established approach to dependency injection, configuration, and exception handling.
Standard Response Format
Successful Response
{
"status": 1,
"page": "/v1/menu",
"body": []
}
body may be an array, a match object, an empty array, or an object containing a
message. Its type depends on the method.
Do not create business logic for unconfirmed status values. After validating the
envelope, always inspect the type and contents of body.
API Error
{
"error_code": 100,
"error_message": "Invalid Package"
}
Check the JSON for API errors instead of relying only on the HTTP status.
event Service Message
{
"status": 1,
"page": "/v1/event",
"body": {
"message": "Game id finished"
}
}
Check body.message before parsing a match object.
Prematch and Live
URLs use two sports line types:
| Value | Data |
|---|---|
line | Prematch — matches that have not started |
live | Live — matches currently in progress |
Rules:
- retrieve and store Prematch and Live separately;
- do not mix responses of the two types in one cache entry;
- do not replace
linewithlivewhen requesting an oldgame_id; - a match receives a new
game_idwhen it moves to Live; - the API does not provide a ready-made link between a Prematch match and its Live version;
- if the project matches them independently, do not present that match as a guaranteed SportAPI relationship.
Step 1: Retrieve the Current Menu
Primary navigation method:
GET /v1/menu/{type}/{lang}
The response contains:
sport
└── country
└── tournament
Use IDs only from a current response of the same sports line type:
body[].idissportId;body[].sub[].idiscountryId;body[].sub[].sub[].idistournamentId.
Do not create a permanent static list of available sports and tournaments. The API
returns only sections that currently contain matches. When the last match disappears,
a tournament or an entire sport may disappear from the next menu response.
If the user needs esports and the method supports this selection, add:
?cybersport=true
Process traditional sports and esports as separate selections when required by the project interface.
Step 2: Retrieve the Match List
GET /v1/events/{sportId}/{tournamentId}/sub/50/{type}/{lang}
Required events rules:
- use only the
subformat; - always pass the technical
countsegment with value50; - do not use
countfor pagination; the result limit has been removed; - pass a tournament ID or
tournamentId=0for every tournament of the selected sport; - even with
tournamentId=0, retrievesportIdfrom the current menu; - use the same
typeandlangas the selected navigation branch.
Response structure:
body[]
└── tournament object
└── events_list[]
└── matches
events contains a short set of main markets and best odds. Do not automatically call
event for every match. Request match details only when the user actually needs them.
Step 3: Retrieve Match Details
Take game_id from the selected match and call:
GET /v1/event/{gameId}/group/{type}/{lang}
Required event rules:
- use only the
groupformat; - pass the same
lineorlivetype from whichgame_idwas retrieved; - do not expect a match array: a successful
bodycontains one object; - check
body.messagefirst; - use
eventfor the complete odds list of the selected match; - preserve the market, column, and selection order created by the API.
The group format already groups and sorts odds. Do not rebuild its structure unless
the interface explicitly requires it.
Identifiers
| Purpose | Field or parameter |
|---|---|
| Sport | sportId in a URL; sport_id in a match object |
| Country | countryId in a URL; country_id in a match object |
| Tournament | tournamentId in a URL; tournament_id in a match object |
| Match or submatch | gameId in a URL; game_id in JSON |
| Main match of a submatch | game_mid |
| Betting selection | oc_pointer |
| Live 3D Tracker | zp |
| Video stream | vi |
Do not derive IDs from names or substitute one identifier for another.
In particular:
game_idrequestsevent;zpis passed asgameidto the ready-made Live 3D Tracker;viis passed to the separate video widget;oc_pointeris used by the separate bet placement and settlement system.
Even if some field values happen to match, their purposes remain different.
Match and Live Data
Account for these fields:
game_start: Unix timestamp in seconds;timer: match timer in seconds;score_full: overall score;score_period: period score;period_name: current period name;finale: completion indicator, not available for every match;extra_time: added time, when populated.
To display minutes, divide timer by 60 and round according to the interface
requirements. Do not request the API every second only to update the timer. Update it
locally and synchronize it during the next scheduled request.
Do not rely on game_num, sgame_id, stat_id, stat_list_extra, or game_plan.
These fields are legacy, reserved, or not currently used by the production API.
Odds
In an events List
game_oc_list contains a short list of markets and best odds. A market’s oc_list is a
flat array:
game_oc_list[]
└── market
└── oc_list[]
└── selection
In Detailed event/group
The outer oc_list contains columns, and each nested array contains the selections for
that column:
game_oc_list[]
└── market
└── oc_list[]
└── column
└── selections
Main selection fields:
| Field | Purpose |
|---|---|
oc_name | Selection name for display |
oc_rate | Current decimal odds |
oc_size | Total, handicap, or another parameter value |
oc_pointer | Unique bet or selection code |
oc_block | true means blocked; false means available |
op_id | Player or participant ID for a player-specific bet |
Processing rules:
- do not require a
1X2market; - do not expect a draw in tennis or basketball;
- available markets depend on the sport and match;
- use
group_idas the technical market ID; - do not use translated names as permanent IDs;
- match selection updates by
oc_pointer, not byoc_rate; - if
oc_block: true, do not allow the selection to be chosen; - if a selection disappears from a new response, do not display its old odds as current;
- do not require
columnsto equal the number of nested arrays; - preserve the order returned by the API.
Submatches
The submatch list is returned only in detailed event, in sub_games.
It may contain:
- a separate half, set, or period;
- corners;
- first-half corners;
- cards;
- fouls;
- player statistics;
- other additional lines.
Each submatch has its own game_id. Request it with the same method:
GET /v1/event/{subgameId}/group/{type}/{lang}
The returned odds apply only to the selected submatch. For example, odds for the “First-half Corners” submatch do not apply to every corner or the entire match.
game_mid contains the main match ID. Do not treat sub_games in an events list as a
data source: the field is not used there and is normally empty.
Group Matches
event_plan is used only in a detailed event response for group events.
The main match may be named “Home — Away,” while event_plan contains the complete list
of actual teams competing on each side. The field is not used in an events list.
Do not confuse event_plan with sub_games.
Live Statistics
Main statistics are returned in stat_list and are available only for Live:
- in the
eventsmatch list; - in a detailed
eventresponse.
The statistic set depends on the sport and specific match. Process the array dynamically
using the actual id, name, opp1, and opp2 values returned.
Do not rename statistics yourself. Do not treat a submatch’s statistics as separate statistics for its type: the main match’s statistics may be repeated in a submatch.
Sport Line API is not a detailed analytics API. Match history, H2H, and team and player analysis belong to a separate service that is under development.
Ready-made Icons
Use the SportAPI CDN in the interface:
| Object | URL template |
|---|---|
| Sport | https://cdn.sportapi.net/sports/v1/color/{sportId}.webp |
| Country | https://cdn.sportapi.net/flags/v1/color/{countryId}.webp |
| Tournament | https://cdn.sportapi.net/tournaments/v1/color/{tournamentId}.webp |
| Team or participant | https://cdn.sportapi.net/opp/v1/color/{iconName}.webp |
For a team, use opp_1_icon or opp_2_icon. Remove the original extension, if present,
before inserting the value into {iconName}.
Provide a fallback when an icon is missing or fails to load.
Update Frequency
Each interval is the minimum delay between requests for the same data set.
| Method | Live | Prematch (line) |
|---|---|---|
menu | at least 20 seconds | at least 60 seconds |
sports, countries, tournaments | at least 60 seconds | at least 120 seconds |
events | at least 7 seconds | at least 30 seconds |
event | at least 5 seconds | at least 30 seconds |
topmatches | at least 30 seconds | at least 120 seconds |
toplist | not used | at least 120 seconds |
Required rules:
- Do not start the next request for the same data before the previous one finishes.
- Do not update
menuat theeventfrequency. - Do not request
eventfor every listed match unless necessary. - After a temporary network error, use an increasing delay.
- Do not automatically retry key, language, subscription, or URL parameter errors.
- If the manager provides different intervals, use the manager’s values.
There is no hard monthly request quota, but violating the intervals or creating excessive load may result in a warning and key suspension until the integration is fixed.
Caching
Caching and processing responses on the client side are allowed and recommended.
When implementing a cache:
- include the method and every parameter that changes the response;
- separate
lineandlive; - account for the language and esports flag;
- do not present an old response as current after receiving a new empty array;
- do not retain a disappeared selection as available;
- do not include the API key in a cache key or stored response body.
Use the project’s existing caching infrastructure. Do not add a new database or external service unless the task requires it.
Empty States and Errors
Handle at least these situations:
| Situation | Action |
|---|---|
body: [] | Show an empty state; do not treat it as a system error |
Game not found | Report that the match is unavailable; refresh the list if needed |
Game id finished | Stop updating the old ID and request current events |
Missing Package header | Check that the Package header is sent |
Invalid Package | Check the key and environment configuration |
Package has expired | Report that access must be renewed |
Access denied | Check the subscription and available sportId |
Invalid language | Check the language code |
The language is not available in your package. | Check subscription languages |
Wrong data type (accept only live or line) | Correct the sports line type value |
| unknown JSON | Record a safe diagnostic error without exposing the key |
| timeout or temporary network error | Show a temporary state and retry after a delay |
Do not use Game id finished to determine whether a match ended, was cancelled, was
postponed, or moved to Live. The API does not distinguish these reasons.
Do not leave an infinite loading indicator. Use the project’s existing loading, empty, and error-state components.
Additional Methods
The following methods are optional. Do not implement or call them automatically unless the project needs them:
| Method | Purpose |
|---|---|
sports | Separate sport list |
countries | Countries for the selected sport |
tournaments | Tournaments for the selected sport and country |
topmatches | Live or Prematch top-match selection |
toplist | Top matches for one selected sport, Prematch only |
search | Match search using URL-encoded text |
Normally use menu, which returns sports, countries, and tournaments in one request.
The step-by-step sports → countries → tournaments chain is needed only for specific
interface scenarios.
Do not use events-by-period. Its contract requires correction and is not ready for
client integration.
Live 3D Tracker and Video
Do not integrate the tracker or video merely because the sports line contains their fields. They are separate paid services with their own keys and access conditions.
Live 3D Tracker
- works only for Live;
- availability is determined by
zp; - the widget’s
gameidequalszp, notgame_id; - do not create the widget when
zp: null; - the tracker must support the sport;
- use the ready-made
iframeorembed.js.
If the user explicitly requests the tracker and has access, follow the Live 3D Tracker integration documentation.
Video Streaming
- available only for some Live matches;
va: 1and a non-emptyvimean video is available;va: nullorvi: nullmeans video is unavailable;viis a string ID, not a URL;- video is displayed in a separate ready-made widget through an
iframe; - SportAPI does not stream matches from top leagues.
Do not develop a custom video player or insert vi directly into src without the
separate video-service documentation.
Bet Placement System
Sport Line API provides data but does not itself create bet slips, accept bets, or settle results.
If the client has a separate bet placement and settlement system:
- use
oc_pointeras the unique code of the selected outcome; - pass it without modification;
- check the current
oc_rateandoc_blockbefore selection; - follow the Bet Pointer and Coupon Placement documentation.
Do not create a fake bet-submission flow based only on Sport Line API.
Implementation Order
- Study the project and locate its existing HTTP client, configuration, cache, and error handling.
- Identify the backend layer where the key can be stored securely.
- Add configuration without committing secret values.
- Implement a shared Sport Line API client.
- Add models or types for the standard envelope and required methods.
- Implement the core
menu → events → eventflow. - Add separate Prematch and Live handling when both are required.
- Implement loading, empty-result, and error states.
- Add caching and updates using the required intervals.
- Add optional methods only when requested by the user.
- Write or update tests.
- Run available project checks: tests, linting, type checks, and build.
- Update the sample configuration and startup instructions without an active key.
If the project already contains part of the integration, do not create a parallel implementation. Inspect and extend the existing code in the established style.
Prohibited Actions
- Do not expose or log the API key.
- Do not request Sport Line API directly from a browser.
- Do not hard-code static IDs without checking the current
menu. - Do not link Prematch and Live by
game_id. - Do not use
game_idin place ofzporvi. - Do not treat
status: 1as a guarantee that data is present. - Do not treat an empty array as a system error.
- Do not expect identical markets, selections, or statistics for every match.
- Do not re-sort
groupmarkets and odds unless necessary. - Do not use
countas a limit or pagination value. - Do not request the API every second to update a timer.
- Do not run parallel update loops for the same data.
- Do not use WebSocket before its official release.
- Do not use
events-by-periodbefore the method is fixed. - Do not add unconfirmed fields, statuses, or values.
- Do not integrate paid additional services without a client request and access.
Verification Checklist
After implementation, verify that:
- The key exists only in protected backend configuration.
- Requests contain the
Packageheader. - Live and Prematch responses are not mixed.
- Navigation IDs come from the current API.
eventsis called withsub/50.eventis called withgroup.tournamentId=0correctly returns tournaments for the selected sport.- The flat
oc_listfromeventsand nestedoc_listfromeventare parsed separately. - Markets and selections are not tied only to a
1X2structure. - A blocked or disappeared selection cannot be chosen as current.
- A submatch is requested with its own
game_id. body: [],Game not found, andGame id finishedare handled separately.- The timer is displayed from seconds without creating one-second API requests.
- Update intervals match the documentation.
- A repeated request does not start before the previous request finishes.
- Icons have a fallback.
- Optional methods are not called unnecessarily.
- The key is absent from logs, the client bundle, test snapshots, and Git.
- Tests, linting, type checks, and build succeed.
- Project documentation lists the required variables and startup procedure.
If a real request cannot be made because the key or an approved environment is unavailable, use saved JSON examples or test fixtures. List the external checks the user must perform after access is available.
Report Format
After implementation, report:
- which files changed;
- where configuration is stored;
- which methods were implemented;
- how Prematch and Live are separated;
- how odds, submatches, and statistics are handled;
- which update intervals are used;
- which errors and empty states are implemented;
- which tests and checks were run;
- which data, keys, or external checks are still required;
- which additional services were intentionally not connected.
Detailed Documentation
Use the following documents as the primary sources for Sport Line API structure and rules:
- Sport Line API Integration Guide
- Quick Start
- Authentication and Access
- Core Concepts
menueventsevent- Field Reference
- Odds
- Statistics
- Submatches
- Error Handling
- Integration Examples
- SportAPI FAQ
SportAPI support: @suport_sportapi.
Official website: sportapi.net.