> For the complete documentation index, see [llms.txt](https://docs.lsports.eu/u/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lsports.eu/u/engage/hyper-livescore/customers-api-guide.md).

# Customers API Guide

## Overview

This document describes the Livescore API endpoints for managing customer packages, subscriptions, fixtures, quota usage, and snapshot requests.

**Base URL:** `https://engage-api.lsports.eu/api/livescore`

***

## Endpoints

### 1. Trigger Snapshot

Triggers a snapshot request for a livescore package. Sends a snapshot event to the messaging system for processing.

This endpoint publishes all upcoming fixtures (not yet started) to your Fixtures Queue.

```
POST https://engage-api.lsports.eu/api/livescore/snapshots/trigger
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "message": "Livescore snapshot request sent successfully",
  "packageId": 123,
  "username": "user@example.com"
}
```

**Validation Error (400)**

```json
{ "error": "PackageId must be a positive integer" }
```

Possible validation errors:

* `"PackageId must be a positive integer"`
* `"Username is required"`
* `"Password is required"`
* `"Invalid package credentials"`

**Server Error (500)**

```json
{ "success": false, "message": "Error message", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/snapshots/trigger \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 2. Activate Package

Activates a livescore package. Validates credentials and updates the package status to active in the database.

If the package is already active, the API returns success with the message `"Package is already active"`.

```
POST https://engage-api.lsports.eu/api/livescore/package/activate
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "message": "Package activation completed successfully",
  "packageId": 123,
  "username": "user@example.com"
}
```

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

Possible validation errors:

* `"PackageId must be a positive integer"`
* `"Username is required"`
* `"Password is required"`
* `"Invalid package credentials"`

**Server Error (500)**

```json
{ "success": false, "message": "Failed to activate package", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/package/activate \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 3. Deactivate Package

Deactivates a livescore package. Validates credentials and updates the package status to inactive in the database.

If the package is already inactive, the API returns success with the message `"Package is already inactive"`.

```
POST https://engage-api.lsports.eu/api/livescore/package/deactivate
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "message": "Package deactivation completed successfully",
  "packageId": 123,
  "username": "user@example.com"
}
```

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

**Server Error (500)**

```json
{ "success": false, "message": "Failed to deactivate package", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/package/deactivate \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 4. Get Package Status

Retrieves the current status of a livescore package without modifying it. Returns whether the package is active or inactive.

```
POST https://engage-api.lsports.eu/api/livescore/package/status
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "status": "active",
  "packageId": 123,
  "username": "user@example.com"
}
```

The `status` field can be either `"active"` or `"inactive"`.

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

**Server Error (500)**

```json
{ "success": false, "message": "Unable to validate package credentials", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/package/status \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 5. Get Subscriptions

Returns the hierarchy subscriptions the package holds, as a flat list. Each item is one subscription you added with `subscriptions/add`. To see every league those subscriptions cover, use `subscriptions/subscribed`.

```
POST https://engage-api.lsports.eu/api/livescore/subscriptions
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "packageId": 123,
  "subscriptions": [
    { "sportId": 6046 },
    { "sportId": 6046, "locationId": 243 },
    { "sportId": 6046, "locationId": 243, "leagueId": 8 }
  ]
}
```

Each item holds only the ids that apply to it. A sport-level subscription has `sportId` only; a location-level subscription adds `locationId`. Items are sorted by sport, then location, then league.

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

**Server Error (500)**

```json
{ "success": false, "message": "Unable to retrieve subscriptions", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/subscriptions \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 6. Available Subscriptions

Returns the sport / location / league hierarchy the package is **allowed** to subscribe to but has **not** yet subscribed to, as a nested tree.

```
POST https://engage-api.lsports.eu/api/livescore/subscriptions/available
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "packageId": 123,
  "sports": [
    {
      "id": 6046,
      "name": "Football",
      "locations": [
        {
          "id": 243,
          "name": "England",
          "leagues": [
            { "id": 8, "name": "Premier League" }
          ]
        }
      ]
    }
  ]
}
```

What is returned:

* Only leagues the package is allowed to subscribe to. With no package filter this is the whole catalog; with a filter it is limited to the sports, leagues, and tours in that filter.
* A league already covered by an active subscription (at sport, location, or league level) is excluded — it appears under `subscriptions/subscribed` instead.
* Sports or locations with no remaining leagues are omitted.

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

**Server Error (500)**

```json
{ "success": false, "message": "Unable to retrieve available subscriptions", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/subscriptions/available \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 7. Subscribed Subscriptions

Returns the sport / location / league hierarchy the package is **currently subscribed** to, as a nested tree. Same request body and response shape as `subscriptions/available`.

```
POST https://engage-api.lsports.eu/api/livescore/subscriptions/subscribed
```

A league is included when the package has an active subscription covering it — a sport-level subscription covers every league in that sport, a location-level subscription covers every league in that location, and a league-level subscription covers that league. Leagues not yet subscribed appear under `subscriptions/available` instead.

**Server Error (500)**

```json
{ "success": false, "message": "Unable to retrieve subscribed hierarchies", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/subscriptions/subscribed \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 8. Add Subscriptions

Subscribes the package to one or more hierarchy items. Each item is a sport, a location inside a sport, or a league. A league can be sent with only `leagueId`; sport and location are resolved from that league.

```
POST https://engage-api.lsports.eu/api/livescore/subscriptions/add
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123",
  "subscriptions": [
    { "sportId": 6046 },
    { "sportId": 6046, "locationId": 243 },
    { "leagueId": 8 }
  ]
}
```

**Item result (200, 207, or 400)**

```json
{
  "packageId": 123,
  "results": [
    { "sportId": 6046, "status": "SUCCESS" },
    { "sportId": 6046, "locationId": 243, "status": "REDUNDANT_HIERARCHY" },
    { "leagueId": 8, "status": "OUTSIDE_PACKAGE_FILTER" }
  ]
}
```

Each result echoes the ids that were sent. Omitted ids are left out of the object.

HTTP status for the batch:

* **200** — every item is `SUCCESS`
* **207** — some items succeeded and some did not
* **400** with the `results` body — every item failed

| `status`                 | Meaning                                                                                                                                                                                                                                       |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SUCCESS`                | Subscribed                                                                                                                                                                                                                                    |
| `MISSING_PARENT_CONTEXT` | The item has no ids, or a location was sent without its sport                                                                                                                                                                                 |
| `INVALID_HIERARCHY`      | The sport, location, or league does not exist, the ids do not belong together, the sport is not supported, or the league is inactive                                                                                                          |
| `REDUNDANT_HIERARCHY`    | Already covered by a subscription at this level or a parent level, including another successful item in the same request                                                                                                                      |
| `OUTSIDE_PACKAGE_FILTER` | The item is outside the package filter. A sport is allowed only when the filter includes that whole sport. A location is allowed only when every active league in it is allowed. A league is allowed when its id or its tour is in the filter |

**Request rejected (400)** — the batch is not processed. There is no `results` array.

```json
{ "error": "Invalid package credentials" }
```

The same shape is returned when the package is missing, is not active, or has no expiration date. The `error` string is the reason.

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/subscriptions/add \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123", "subscriptions": [{"sportId": 6046}]}'
```

***

### 9. Remove Subscriptions

Removes hierarchy subscriptions. The package filter is not applied on remove.

```
POST https://engage-api.lsports.eu/api/livescore/subscriptions/remove
```

Same request body as `subscriptions/add`. Same batch HTTP statuses: **200** when every item succeeds, **207** when mixed, **400** with `results` when every item fails, and **400** `{ "error": "..." }` when the request is rejected before items are processed.

| `status`                 | Meaning                                                                                                         |
| ------------------------ | --------------------------------------------------------------------------------------------------------------- |
| `SUCCESS`                | The hierarchy subscription was removed, or fixture subscriptions that were added manually under it were revoked |
| `MISSING_PARENT_CONTEXT` | The item has no ids, or a location was sent without its sport                                                   |
| `INVALID_HIERARCHY`      | The sport, location, or league does not exist, the ids do not belong together, or the sport is not supported    |
| `NOT_SUBSCRIBED`         | Nothing was subscribed at that hierarchy item                                                                   |

***

### 10. Available Fixtures

Returns the fixtures the package can still add with `fixtures/add`. Results are paged and can be narrowed to a sport, location, or league.

```
POST https://engage-api.lsports.eu/api/livescore/fixtures/available
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123",
  "sportId": 6046,
  "locationId": 243,
  "leagueId": 8,
  "skip": 0,
  "take": 100
}
```

| Field        | Required | Description                                               |
| ------------ | -------- | --------------------------------------------------------- |
| `sportId`    | No       | Return fixtures in this sport only                        |
| `locationId` | No       | Return fixtures in this location only. Requires `sportId` |
| `leagueId`   | No       | Return fixtures in this league only                       |
| `skip`       | No       | Number of fixtures to skip. Default 0, maximum 10,000     |
| `take`       | No       | Number of fixtures to return. Default 100, maximum 500    |

Values above the maximum are capped at the maximum.

**Success (200)**

```json
{
  "success": true,
  "packageId": 123,
  "fixtures": [
    {
      "fixtureId": 1001,
      "startDate": "2026-10-14T18:00:00",
      "sport": { "id": 6046, "name": "Football" },
      "location": { "id": 243, "name": "England" },
      "league": { "id": 8, "name": "Premier League" }
    }
  ]
}
```

What is returned:

* Fixtures with livescore coverage in a supported sport.
* Fixtures that are not in a final status (Finished, Cancelled, Abandoned, or Unknown). In-progress fixtures are included.
* Fixtures inside the package filter, when the package has one.
* Fixtures the package is not already subscribed to. Subscribed and pending fixtures appear under `fixtures/subscribed` instead.

`startDate` is in UTC. Fixtures are sorted by `fixtureId`, ascending. To read every page, increase `skip` by `take` until a page returns fewer than `take` fixtures. A `sportId` that is not supported returns an empty `fixtures` list.

**Validation Error (400)**

```json
{ "error": "sportId is required when locationId is specified" }
```

Possible validation errors:

* `"Invalid package credentials"`
* `"hierarchy ids must be positive when provided"`
* `"sportId is required when locationId is specified"`

**Server Error (500)**

```json
{ "success": false, "message": "Unable to retrieve available fixtures", "packageId": 123 }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/fixtures/available \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123", "sportId": 6046, "take": 100}'
```

***

### 11. Subscribed Fixtures

Returns the fixtures the package is subscribed to, including pending ones. This covers fixtures added with `fixtures/add` and fixtures covered by your hierarchy subscriptions.

```
POST https://engage-api.lsports.eu/api/livescore/fixtures/subscribed
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123"
}
```

**Success (200)**

```json
{
  "success": true,
  "packageId": 123,
  "fixtures": [
    {
      "fixtureId": 1001,
      "subscriptionStatus": "Subscribed",
      "sport": { "id": 6046, "name": "Football" },
      "location": { "id": 243, "name": "England" },
      "league": { "id": 8, "name": "Premier League" }
    }
  ]
}
```

| `subscriptionStatus` | Meaning                                                                            |
| -------------------- | ---------------------------------------------------------------------------------- |
| `Subscribed`         | The fixture is active and counts toward your quota                                 |
| `Pending`            | The fixture is waiting for quota. It moves to `Subscribed` when quota is available |

What is returned:

* Fixtures sorted by start date, newest first.
* Finished fixtures stay in the list. Cancelled, Abandoned, and Unknown fixtures are left out.

This endpoint returns `subscriptionStatus` as text. The add and remove endpoints return it as a number (1 subscribed, 2 pending).

**Validation Error (400)**

```json
{ "error": "Invalid package credentials" }
```

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/fixtures/subscribed \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

### 12. Add Fixtures

Subscribes the package to specific fixtures.

```
POST https://engage-api.lsports.eu/api/livescore/fixtures/add
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123",
  "fixtureIds": [1001, 1002]
}
```

**Item result (200, 207, or 400)**

```json
{
  "packageId": 123,
  "results": [
    { "fixtureId": 1001, "status": "SUCCESS", "subscriptionStatus": 1 },
    { "fixtureId": 1002, "status": "OUTSIDE_PACKAGE_FILTER" }
  ]
}
```

`subscriptionStatus` is present only on `SUCCESS`: **1** subscribed, **2** pending.

Batch HTTP statuses match `subscriptions/add`: **200**, **207**, or **400** with `results`. A rejected request is **400** `{ "error": "..." }` with no `results` array. An empty `fixtureIds` list returns `{ "error": "fixtureIds must contain at least one item" }`.

| `status`                 | Meaning                                                                                                                                                                             |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SUCCESS`                | Added. `subscriptionStatus` 1 is subscribed; 2 is pending                                                                                                                           |
| `INVALID_FIXTURE`        | The fixture cannot be subscribed. It does not exist, it is not a livescore fixture, its sport is not supported, or it is already in a final status. An in-progress fixture is valid |
| `ALREADY_SUBSCRIBED`     | Already subscribed                                                                                                                                                                  |
| `OUTSIDE_PACKAGE_FILTER` | The fixture is eligible, but its sport, league, or tour is outside the package filter                                                                                               |

**cURL**

```bash
curl -X POST https://engage-api.lsports.eu/api/livescore/fixtures/add \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123", "fixtureIds": [1001]}'
```

***

### 13. Remove Fixtures

Removes fixture subscriptions. The package filter is not applied on remove.

```
POST https://engage-api.lsports.eu/api/livescore/fixtures/remove
```

Same request body as `fixtures/add`. Same batch HTTP statuses.

| `status`         | Meaning                                                       |
| ---------------- | ------------------------------------------------------------- |
| `SUCCESS`        | Removed. `subscriptionStatus` 3 is unsubscribed; 4 is deleted |
| `NOT_SUBSCRIBED` | The package was not subscribed to that fixture                |

***

### 14. Quota Usage

Returns the package quota for the current billing period: the total, how much is used, and how much is left. Optionally includes the fixtures that are using it.

```
POST https://engage-api.lsports.eu/api/livescore/quota-usage
```

**Request body**

```json
{
  "packageId": 123,
  "username": "user@example.com",
  "password": "password123",
  "includeFixtures": false
}
```

Set `includeFixtures` to `true` to add the `fixtures` list to the response. You can also pass it as a query parameter (`/quota-usage?includeFixtures=true`). The query parameter takes priority over the body.

**Success (200)**

```json
{
  "success": true,
  "periodStartDate": "2026-10-05T00:00:00Z",
  "periodEndDate": "2026-11-05T00:00:00Z",
  "totalQuota": 500,
  "totalConsumed": 120,
  "remainingQuota": 380,
  "expirationDate": "2027-03-05T00:00:00Z"
}
```

| Field             | Description                                                                             |
| ----------------- | --------------------------------------------------------------------------------------- |
| `periodStartDate` | Start of the current billing period (UTC, inclusive)                                    |
| `periodEndDate`   | End of the current billing period (UTC, exclusive)                                      |
| `totalQuota`      | Fixtures the package can use in one billing period                                      |
| `totalConsumed`   | Fixtures used in the current billing period                                             |
| `remainingQuota`  | `totalQuota` minus `totalConsumed`                                                      |
| `expirationDate`  | Package expiration date (UTC)                                                           |
| `fixtures`        | Present only when `includeFixtures` is `true`. Same item shape as `fixtures/subscribed` |

How quota is counted:

* The billing period is one month, starting on the same day of the month as the package expiration date. If that day is after the 27th, the period starts on the 1st of the month.
* A fixture uses quota once it is charged in the current period. Removing a charged fixture does not return its quota.
* The `fixtures` list holds `Subscribed` fixtures only. Pending fixtures are left out because they do not use quota yet.

**Validation Error (400)**

```json
{ "error": "Package has no expiration_date; billing period cannot be computed." }
```

Possible validation errors:

* `"Invalid package credentials"`
* `"Package has no expiration_date; billing period cannot be computed."`

**Server Error (500)**

```json
{ "success": false, "message": "Unable to retrieve quota usage", "packageId": 123 }
```

**cURL**

```bash
curl -X POST "https://engage-api.lsports.eu/api/livescore/quota-usage?includeFixtures=true" \
  -H "Content-Type: application/json" \
  -d '{"packageId": 123, "username": "user@example.com", "password": "password123"}'
```

***

## Authentication

All endpoints require authentication via the `username` and `password` fields in the request body. The credentials are validated against the stored package credentials in the database.

***

## Error Handling

**Validation Errors (400)** — Returned when:

* Required fields are missing or invalid
* Package credentials don't match
* Package doesn't exist, is not active, or has no expiration date

Add and remove endpoints also return **400** with a `results` array when every item fails, and **207** when some items succeed. Read each item's `status` in sections 8, 9, 12, and 13. A rejected request has `{ "error": "..." }` and no `results` array.

**Server Errors (500)** — Returned when:

* Database connection fails
* External API calls fail
* Unexpected server-side errors occur

***

## See also

* [Metadata API Guide](/u/engage/hyper-livescore/metadata-api-guide.md) — look up sport, location, league, period, and incident reference data


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.lsports.eu/u/engage/hyper-livescore/customers-api-guide.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
