The free key reads yesterday again: our one-month trial of today on the free key has finished. Read the changelog

Authentication

One header. No tokens to refresh, no OAuth dance.

Send your key on every request in either of two headers. Both are read the same way, and there are no tokens to refresh and no signing to implement.

1. X-API-Key, the simplest:

curl "https://api.footballsoccerapi.com/v1/matches?limit=5" \
  -H "X-API-Key: fsa_live_8f3c2b91d4e7a06c5b8"

2. Authorization: Bearer, for clients and tools that only send that header (MCP clients, API gateways, OpenAPI tooling):

curl "https://api.footballsoccerapi.com/v1/matches?limit=5" \
  -H "Authorization: Bearer fsa_live_8f3c2b91d4e7a06c5b8"

If both are sent, X-API-Key is used.

Never in the address

A key in the address (?key= or ?api_key=) is refused with 400 key_in_address. Addresses end up in server logs, proxies, browser history and screenshots, so a key there is a key leaked.

In these docs

The key you were given at sign-up is already in the Try it box on every endpoint page, kept in this browser only. A key you make or rotate in your account replaces it there too.

Keep it server-side

Never put your key in a browser or a mobile app. Anything shipped to a device can be read off it. Call the API from your own server and pass the result on.

Calls made with your key count against your limits and count as made by you.

Rotating

If a key leaks, rotate it from your account. A new key is issued immediately and the old one stops working the moment you confirm: anything still using it starts getting 401s, so update your code first.

What failure looks like

A missing or unknown key returns 401, a key in the address 400. A key that is valid but on a plan that does not reach the endpoint returns 403 naming the plan it needs. Neither is ever a bare refusal: see errors.