SportAPI Documentation
EN
3D Product documentationLive 3D Tracker
v1
Service & pricing ↗ Get access ↗
Live 3D Tracker / Live 3D Tracker integration task

Task for an AI agent: integrate Live 3D Tracker

Purpose of this document

This file contains a task for an AI agent that must integrate Live 3D Tracker into an existing client website or web application.

Implement the integration according to the project’s architecture and style. Do not change existing functionality, design, or project structure unless needed.

Information required before starting

Inspect the project and find or request the following information from the user:

  1. The page or component where the tracker must be displayed.
  2. An access key in the pk_live_... format issued by a SportAPI manager.
  3. A production or test domain activated for that key.
  4. The SportAPI sports-line data source.
  5. The zp field in the selected match data.
  6. The sport ID from the table below.
  7. The required interface language.
  8. Height and mobile-layout requirements.

If the key or other required information is missing, do not invent it. Prepare the integration with clear placeholder variables and tell the user what still needs to be obtained.

To obtain a key and activate a domain, the user must contact the SportAPI manager on Telegram. For local development, tell the manager separately that the key must work on localhost.

Core rules

  • The tracker works only for matches with live status.
  • The tracker does not provide a sports line or a match list.
  • A SportAPI sports-line subscription is required to obtain match data and the zp field.
  • The gameid parameter always comes from zp: gameid = zp.
  • If zp is missing or equals null, the tracker is unavailable for that match. Do not create an empty widget.
  • Pass the correct sport ID in the sport parameter.
  • Available sports and languages may be limited by the key’s plan.
  • The key may be used in client-side code because it is protected by an allowlist of authorized domains.
  • Do not add unsupported styling parameters or modify the tracker design. SportAPI provides custom visual changes as a separate service.

Demo

The tracker appearance can be viewed on the demonstration page.

The demonstration does not use real live data and does not replace testing the integration with a live match whose zp value is not null.

Sport IDs

IDSport
1Football
2Ice hockey
3Basketball
4Tennis
5Baseball
6Volleyball
7Rugby
8Handball
10Table tennis
13American football
17Water polo
21Darts
26Formula 1
28Australian football
44Horse racing
66Cricket
86CS:GO / esports

Do not assume that an internal sport ID in the client project matches an ID in this table. If the project uses its own identifiers, create an explicit mapping.

Choose an integration method

Use a direct iframe when the page only needs to display one match and the project does not require advanced widget control.

Use embed.js when the user switches matches on the same page or when the project needs to control standard parameters through JavaScript.

Method 1. Direct iframe

Basic example:

<iframe
  id="live-tracker"
  src="https://bet-embed-sport-tracker.vercel.app/?key=pk_live_yourkey&gameid=745829876&sport=1&lang=en"
  style="width: 100%; height: 360px; border: none; display: block;"
  allowfullscreen
  title="Live tracker"
></iframe>

Standard URL parameters:

  • key — client access key;
  • gameid — value of the zp field;
  • sport — sport ID;
  • lang — interface language;
  • mobile=1 — mobile layout;
  • view=2d or view=3d — available display mode.

The simplest way to switch a match is to change gameid and sport in the iframe element’s src attribute.

A match can also be changed without reloading the iframe by using postMessage. Send the message only after the iframe has loaded or in response to a user action:

const trackerFrame = document.querySelector('#live-tracker');
let trackerLoaded = false;

trackerFrame.addEventListener('load', () => {
  trackerLoaded = true;
});

function switchMatch(gameid, sport) {
  if (!trackerLoaded) return;

  trackerFrame.contentWindow.postMessage(
    {
      type: 'CONFIG',
      payload: { gameid, sport }
    },
    'https://bet-embed-sport-tracker.vercel.app'
  );
}

Do not use '*' as targetOrigin.

Method 2. Integration with embed.js

Loader URL:

https://bet-embed-sport-tracker.vercel.app/embed.js

Basic example:

<div id="zone"></div>

<script src="https://bet-embed-sport-tracker.vercel.app/embed.js"></script>
<script>
  let trackerReady = false;

  window.addEventListener('message', (event) => {
    if (event.origin !== 'https://bet-embed-sport-tracker.vercel.app') return;

    if (event.data?.type === 'READY') {
      trackerReady = true;
    }
  });

  const zone = BetZoneEmbed.init({
    container: '#zone',
    key: 'pk_live_yourkey',
    gameid: 745829876,
    sport: 1,
    lang: 'en',
    height: 360
  });

  function switchMatch(gameid, sport) {
    if (!trackerReady) return;
    zone.update({ gameid, sport });
  }

  function switchLanguage(lang) {
    if (!trackerReady) return;
    zone.update({ lang });
  }
</script>

Do not call zone.update() immediately after init(). The iframe may still be loading, so the message would be lost. Call update() after receiving READY or later in response to a user action.

Standard init() parameters:

ParameterRequiredTypeDefaultPurpose
containeryesstring or Elementwidget container
keyyesstringaccess key
gameidyesnumbervalue of the zp field
sportyesnumbersport ID
langnostringruinterface language
heightnonumber360height in pixels
mobilenobooleanfalsemobile layout

The update() method can change gameid, sport, lang, mobile, and view without recreating the widget.

When the tracker component or block is removed from the page, call:

zone.destroy();

React, Vue, Svelte, and other SPAs

When integrating into an SPA:

  1. Load the external script after mounting the component or use the framework’s standard script-loading mechanism.
  2. Do not add the same <script> on every render.
  3. Do not access window or the DOM during server-side rendering.
  4. Call init() only after the container exists in the DOM and embed.js has loaded.
  5. Store the object returned by init().
  6. When the match changes, call update() only after the widget is ready.
  7. On unmount, call destroy() and remove the event listeners you created.

Use the project’s existing conventions for script loading, configuration storage, state handling, and responsive layout.

States and errors

Handle the following situations:

SituationAction
key is missingdo not start the widget; explain which key is required
current domain is unauthorized or key is disabledshow an access error and tell the user to contact SportAPI
403 responseverify the key and domain binding
match is not livedo not display the tracker
zp is missing or equals nulldo not create the widget; show a fallback or hide the block
sport or language is not included in the plando not treat this as an integration error; explain the key limitation
user selects another matchcall update() after the widget is ready
component is removedcall destroy() and remove event listeners

Do not leave the page in an infinite loading state. Use the project’s existing loading, empty-state, and error components.

Responsive behavior

  • The tracker width must be 100% of its container.
  • Recommended desktop height: 360–420 px.
  • Recommended mobile height: 220–280 px.
  • Use mobile: true or mobile=1 for the mobile layout.
  • Do not set a fixed pixel width.

Use the existing project’s breakpoints and design system.

Verify the result

After implementation, verify that:

  1. The widget loads on an authorized domain with a valid key.
  2. The widget is not created when zp: null.
  3. A non-live match does not display the tracker.
  4. gameid receives the value of the zp field.
  5. The sport code matches the table or an explicit project ID mapping.
  6. update() is not called before READY.
  7. The match and language change without a full page reload.
  8. A direct iframe receives CONFIG only after loading.
  9. Appropriate dimensions are used on mobile and desktop.
  10. Repeated mounting does not create duplicate scripts, iframes, or listeners.
  11. destroy() is called when the component is removed.
  12. Available tests, linting, type checks, and the project build pass.

If the integration cannot be fully tested because a key, authorized domain, or live match with zp is unavailable, perform every available check and list what the user must verify after obtaining access.

Report format

After completion, tell the user:

  • which files were changed;
  • which integration method was selected and why;
  • where gameid and sport come from;
  • which error states were implemented;
  • which checks were completed;
  • which data or external checks are still required.

SportAPI support: @suport_sportapi.