Building with AI? Give your coding tool the whole reference in one file: https://soccer-data.co/llms.txt
SOCCER DATA Docs
Sign in Get API key
// Get started

Authentication

Send your API key with every request, and keep it on your server.

Every request needs an API key. You send it in a header, we check it, and the request counts against your plan.

Sending your key

Put the key in the X-Api-Key header:

curl "https://api.soccer-data.co/v1/competitions?per_page=1" \
  -H "X-Api-Key: YOUR_API_KEY"
const res = await fetch("https://api.soccer-data.co/v1/competitions?per_page=1", {
  headers: { "X-Api-Key": process.env.SOCCER_DATA_KEY },
});
console.log(res.status, await res.json());
import os, requests

res = requests.get(
    "https://api.soccer-data.co/v1/competitions",
    params={"per_page": 1},
    headers={"X-Api-Key": os.environ["SOCCER_DATA_KEY"]},
)
print(res.status_code, res.json())
$response = Http::withHeaders(['X-Api-Key' => env('SOCCER_DATA_KEY')])
    ->get('https://api.soccer-data.co/v1/competitions', ['per_page' => 1]);

If your HTTP client is already set up for bearer tokens, Authorization: Bearer YOUR_API_KEY works too. Use one or the other.

Note Keys only work in a header. A key added to the URL as a query parameter is ignored, and the request fails with 401.

Managing keys

Your first key is made for you when you sign up. Create more, and revoke them, on the API keys page of your dashboard.

  • Keys start with sd_.
  • Give each key a name, such as the app or environment that uses it, so you can tell them apart later.
  • We show a new key in full only once. Copy it before you leave the page.
  • You can hold up to 10 active keys at a time.
  • All your keys share your account's per-minute and daily limits. See Rate limits.

Revoking and rotating

Revoking a key stops it at once; any request that still uses it gets 401. If a key might have leaked, rotate it without downtime:

  1. Create a new key.
  2. Put the new key on your server and deploy.
  3. Revoke the old key.

Keeping your key safe

Your key is tied to your account and your plan. Anyone who has it can spend your requests.

  • Call the API from your server. If you have a website or a mobile app, have it call a route on your own server, and let only that route talk to Soccer Data. Anything that runs in a browser can be read by visitors in the page source or the network tab.
  • Read the key from an environment variable. Don't hard-code it, and add .env to .gitignore.
  • Watch out for public variables. Variables that start with NEXT_PUBLIC_ or VITE_ are bundled into browser code, so they are no place for a key.
  • Use your platform's secrets store. In tools like Lovable, use the Add secret form and call the API from a server function, since the project's .env file may be committed.
  • Keep it out of sight. Don't paste the key into logs, screenshots, support tickets or AI chats.

Environment variables

# .env (keep this file out of git)
SOCCER_DATA_KEY=YOUR_API_KEY
// config.js
export const apiKey = process.env.SOCCER_DATA_KEY;
if (!apiKey) throw new Error("SOCCER_DATA_KEY is not set");

In Node.js 20.6 or later, node --env-file=.env app.js loads the file for you; on older versions use the dotenv package. In Python, python-dotenv does the same job before you read os.environ["SOCCER_DATA_KEY"].

A server route in Next.js

This route handler keeps the key on the server. Your page calls /api/next-fixture, and only the server talks to Soccer Data:

// app/api/next-fixture/route.js
export async function GET() {
  const params = new URLSearchParams({
    team_id: "team_f0ibhxdw7hs5",
    status: "scheduled",
    sort: "utc_date",
    per_page: "1",
  });

  const res = await fetch(`https://api.soccer-data.co/v1/matches?${params}`, {
    headers: { "X-Api-Key": process.env.SOCCER_DATA_KEY },
  });

  return Response.json(await res.json(), { status: res.status });
}

When something goes wrong

Authentication problems use the same error shape as everything else:

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Send your API key in the X-Api-Key header. You can create one in your dashboard.",
    "status_code": 401
  }
}
Status Code What it means What to do
401 UNAUTHORIZED No key was sent. Add the X-Api-Key header.
401 UNAUTHORIZED The key is wrong or has been revoked. Check for missing characters or extra spaces, or create a new key.
403 PLAN_UPGRADE_REQUIRED The endpoint isn't part of your plan. Odds need a paid plan. Upgrade on the plans page, or use another endpoint.
429 RATE_LIMITED or USAGE_LIMIT_EXCEEDED You've hit the per-minute or daily limit. Wait the number of seconds in Retry-After.

Note Too many requests with invalid keys from the same address within a minute get a 429 RATE_LIMITED for a short while. Fix the key, then wait for Retry-After.

Once your key is accepted, every response, errors included, carries your rate limit headers. Rate limits explains them.

Next steps