Technical reference

Endpoint catalog

Every route open to external calls, with accepted parameters, a ready-to-run request and the exact response structure. All respond to GET unless stated otherwise.

37
endpoints
6
families
Base URL
https://api.emcurso.pt
Account and key

GET /key

Data for the key used in the request — name, entity, authorised endpoints, required User-Agent — and the current state of the three limit windows (minute, hour, day), including when each one resets.

Available with any key, whatever allowedEndpoints holds: this call is not checked against the authorised endpoints and does not spend quota, precisely so it can be used to check what is left. Once a window has rolled over, used comes back 0 and resetAt comes back null.

Parameters

This endpoint takes no parameters.

GET/keySimulated
curl -H "Authorization: Bearer $EMCURSO_KEY" "https://api.emcurso.pt/key"

Data about the key itself, returned by EmCurso

Authentication

Authentication and access keys

All external requests are authenticated with a key in the Authorization header, in Bearer form. Keys are issued to a named holder, revocable at any time, and can be restricted to a subset of endpoints and to a declared User-Agent.

200 · authenticated

$ curl -sD - -H "Authorization: Bearer $EMCURSO_KEY" \
    "https://api.emcurso.pt/prociv/incendios/ativos"

HTTP/2 200
content-type: application/json; charset=utf-8
cache-control: public, s-maxage=30, stale-while-revalidate=60
x-cache: HIT
x-auth-method: bearer
x-ratelimit-limit: 60
x-ratelimit-remaining: 57
x-ratelimit-reset: 2026-08-01T11:43:00.000Z
x-ratelimit-reset-after: 38
x-ratelimit-window: minute

401 · no key

$ curl -sD - "https://api.emcurso.pt/prociv/incendios/ativos"

HTTP/2 401
www-authenticate: Bearer realm="EmCurso API"
content-type: application/json
x-request-id: 8f1c2e40-9b3a-4d61

{
  "success": false,
  "error": "Unauthorized",
  "message": "Missing or invalid API key",
  "requestId": "8f1c2e40-9b3a-4d61",
  "hint": "Para acesso externo, use Authorization: Bearer <API_KEY>"
}

What each status means

200
Request served
X-Cache says whether it came from cache (HIT), from origin (MISS), or from a stale copy served while revalidating (STALE).
401
Key missing, invalid or revoked
The message field says which of the three. Check the header before suspecting the key — a path that does not exist answers 404, never 401.
403
User-Agent refused
The key requires a declared User-Agent and the one sent does not match. The observed identifiers are listed in the console.
429
Limit exceeded
Retry-After states the seconds to wait and is never zero. The body repeats it in retryAfterSeconds, alongside resetAt and the window that fired.
404
Path does not exist
Returned to any caller, with or without a key. A caller sending an issued key also receives the near matches and the full list.

Every response carries X-Request-ID, repeated in the body of a refusal. That is the identifier to quote when reporting a problem.

Quotas

Usage limits

Each key carries its own limits, set when the request is reviewed, against the stated purpose and expected volume. The values below are what an ordinary integration receives; one that needs more asks for it in the console, with a justification.

requestsX-RateLimit-Window
60per minuteminuteprotects the origin from bursts
1 000per hourhouraccommodates regular polling
10 000per daydaythe key's daily ceiling

All three windows are checked at once. Whichever runs out first is the one that answers 429, and its name is what X-RateLimit-Window carries.

On every response
x-ratelimit-limit: 60
x-ratelimit-remaining: 57
x-ratelimit-reset: 2026-08-01T11:43:00.000Z
x-ratelimit-reset-after: 38
x-ratelimit-window: minute
429 · limit exceeded
HTTP/2 429
retry-after: 38
x-ratelimit-limit: 60
x-ratelimit-remaining: 0
x-ratelimit-window: minute

{
  "success": false,
  "error": "Too Many Requests",
  "retryAfterSeconds": 38,
  "resetAt": "2026-08-01T11:43:00.000Z",
  "limit": 60,
  "window": "minute",
  "hint": "Limite excedido. Repetir dentro de 38s."
}

Retry-After is never zero, so it can be wired straight into a backoff without inventing a fallback. X-RateLimit-Reset-After says the same in seconds, and X-RateLimit-Reset gives the instant in ISO-8601.

The service runs on free community infrastructure. Availability is best-effort with no latency guarantee; intensive or sustained use requires prior agreement.