# KickoffAPI — PHP SDK

One file, `ext-curl`, no Composer. PHP 7.4+.

```php
<?php
require_once "KickoffApi.php";

$api = new KickoffApi("YOUR_API_KEY");   // free key: https://kickoffapi.com/portal/

$live = $api->live_scores();             // { data: [...], meta: {...} }
$epl  = $api->standings(["league" => "lg_8K3mZ0pQ", "season" => 2025]);
$fx   = $api->fixture("fx_99Xy");
```

Talks to **v2** by default (`https://api.kickoffapi.com/api/v2`), so every method
returns the unified `{ data, meta }` envelope with v2's native ids (`lg_…`,
`tm_…`, `fx_…`). Pass a different base URL as the second argument for the
legacy API. See the [v2 reference](https://docs.kickoffapi.com/api-v2-reference.html)
or the [v1 reference](https://docs.kickoffapi.com/api-v1-reference.html) (legacy,
sunsets 01 Jan 2027).

## Methods

One per v2 endpoint, named exactly as the Python client names it
(`live_scores()`, `head_to_head()`, `xg_batch()`, …) so the same call reads the
same in every official SDK. `get()`/`post()` are there for anything without a
named method yet.

```php
$api->countries(["limit" => 50]);
$api->leagues(["country" => "England"]);
$api->fixtures(["league" => "lg_8K3mZ0pQ", "season" => 2025, "limit" => 20]);
$api->fixture_events("fx_99Xy", ["refresh" => 1]);
$api->top_scorers(["league" => "lg_8K3mZ0pQ", "season" => 2025]);
$api->odds(["fixture" => "fx_99Xy"]);
$api->xg(["x" => 110, "y" => 38, "bodyPart" => "Right Foot", "situation" => "Open Play"]);
$api->xg_batch([["x" => 110, "y" => 38], ["x" => 118, "y" => 41, "situation" => "Penalty"]]);
$api->resolve(["entity" => "team", "legacyId" => 33]);
$api->account_status();
```

## Errors

Every non-2xx response throws `KickoffApiException`, which carries the status and
the message the API sent back. A 429 also carries the `Retry-After` wait:

```php
try {
    $fx = $api->fixture("fx_does_not_exist");
} catch (KickoffApiException $e) {
    $e->status;       // 404
    $e->getMessage(); // "fixture not found"
}

try {
    $api->countries(["limit" => 5000]);
} catch (KickoffApiException $e) {
    if ($e->status === 429 && $e->retryAfter !== null) {
        sleep($e->retryAfter);   // the API told us how long to wait
    }
}
```

Spec: `/openapi-v2.yaml`.
