Delivery · Widgets
Live sport on any page, without a backend
Widgets put live scores, a match centre or a league table into a web page with plain HTML. They run in your visitor's browser, talk to the API with a key that is safe to publish, and carry no logo of ours, so they look like part of your site.
- Free: not included
- Starter: not included
- Pro: included
- Business: included
Two tags and a key
Create a widget key, tell it which sites may use it, paste the snippet. There is nothing to deploy on your side.
- 01
Create a widget key
In the dashboard's Widgets tab. It starts with dsa_pub_.
- 02
List your sites
The origins allowed to use the key: exact ones, or a wildcard for every subdomain.
- 03
Paste the snippet
One element per widget, one script tag per page. The dashboard previews every option with sample data first.
A key that is meant to be seen
A dsa_pub_ key sits in your page source on purpose. Three locks make that safe.
Only from your sites
The browser's Origin header must match an entry on the key's list, either exactly (https://www.example.com) or by subdomain wildcard (https://*.example.com). Requests without an Origin are refused too: widget keys are for browsers.
Only what widgets read
Live scores; a fixture with its events, lineups and statistics; league seasons and standings. Nothing else in the API answers to it.
Only while your plan allows
Widgets come with Pro and Business. If the account moves to a plan without them, the key stops working.
The embed
Put an element wherever a widget should appear, then load the script once, with your key on it.
<!-- 1. Place one element per widget at the spot it should render -->
<div data-dsa-widget="livescore" data-sport="football" data-league="17"></div>
<div data-dsa-widget="standings" data-league="17" data-theme="dark"></div>
<!-- 2. The script, once per page, with your widget key -->
<script src="https://datasportsapi.com/embed/v1.js" data-key="dsa_pub_…" async></script>The script scans the page for elements with data-dsa-widget, fetches their data with the key from data-key and renders each one in place. Load it with async so it never holds up your page.
The script is served from https://datasportsapi.com and reads its data from api.datasportsapi.com. If your site sends a strict Content Security Policy, allow both.
Three widget types
The value of data-dsa-widget picks the type; the other attributes say what it should show.
| data-dsa-widget | Shows | Attributes | Default refresh |
|---|---|---|---|
livescore | The matches of one sport that are in play right now, grouped by competition. |
| 30 s |
match | One match: the score, its status and a timeline of goals, cards and substitutions. |
| 30 s |
standings | A season's main league table. |
| 600 s |
Roughly how each type looks
Sample dataEngland · Premier League
- 63'ArsenalChelsea11
Spain · LaLiga
- 37'Real MadridAthletic Club20
Türkiye · Süper Lig
- 12'GalatasarayFenerbahçe00
Premier League
63' · 2nd half
- 22'GoalARS
- 41'Yellow cardCHE
- 55'GoalCHE
- 60'SubstitutionARS
| # | Team | P | Pts |
|---|---|---|---|
| 1 | Arsenal | 11 | 26 |
| 2 | Chelsea | 11 | 23 |
| 3 | Liverpool | 11 | 22 |
| 4 | Aston Villa | 11 | 19 |
| 5 | Brighton | 11 | 18 |
Options
Every type accepts the same four optional attributes.
| Attribute | Values | Effect |
|---|---|---|
data-size | small | medium | large | How much room the widget takes. medium is the default. See the ruler below. |
data-theme | light | dark | auto | auto follows the visitor's own light or dark setting. |
data-accent | #hex | Your brand colour for highlights, e.g. #e4002b. |
data-refresh | seconds, 15 or more | How often the widget reloads its data. Defaults: 30 for livescore and match, 600 for standings. |
small≤ 340 pxA sidebar. Compact rows; tables keep only P and Pts.
medium≤ 640 pxA content column. The default.
largefull widthThe whole container, with larger type.
Theme and styling
Widgets render inside their own shadow root. Your stylesheet cannot break them, and cannot restyle them either.
data-theme="light"Light surfaces and dark text, for light pages.
data-theme="dark"Dark surfaces and light text, for dark pages.
data-theme="auto"Follows the light or dark setting of the visitor's own device.
Add data-accent with a hex colour to bring in your brand. Between the theme, the accent and the three sizes, most sites can match their own look without writing any CSS; the dashboard's Widgets tab lets you try every combination on sample data before you embed.
What a widget costs
Each time a widget refreshes, that is one request against your quota, from every browser that has it open.
The arithmetic is simple and it adds up quickly: keep one livescore widget, refreshing every 30 seconds, on screen in 100 browsers for an hour and you have made 100 × 120 = 12,000 requests. Try your own numbers:
Requests it costs
- Per day
- 12,000
- Per 30 days
- 360,000
- Pro36.0% of 1,000,000 / month
- Business3.6% of 10,000,000 / month
Widget refreshes share the quota with every other call your account makes.
Slow down what moves slowly
Standings change after matches, not every 30 seconds. The 600-second default is there for a reason.
Show live only where it is live
A match widget on an article from last week does not need to refresh. Remove it, or raise data-refresh.
Mind the per-minute rate
Many visitors arriving at once all refresh in the same minute, which counts against your rate as well as your quota.
Quotas and rates per plan: Plans, quota & rate limits.
Troubleshooting
- The widget stays empty and the console shows a 403
- 403origin_not_allowed means the page's origin is not on the key's list. Origins are exact:
https://example.comandhttps://www.example.comare two different entries, and so are http and https. Add the missing one, or use a wildcard for subdomains. - 403 endpoint_not_in_plan
- Either the account's plan does not include widgets (they need Pro or Business), or the key was used for something widgets never read. A publishable key cannot reach the rest of the API.
- It worked, then stopped mid-month
- The quota is spent: every widget refresh is a request. Look for 429quota_exceeded, then raise
data-refreshor remove widgets that nobody needs to see live. - My CSS does not change it
- By design. The widget renders inside its own shadow root, so page styles cannot leak in. Use
data-themeanddata-accentinstead.