login
quiescence.eu

Funding API

Read access to the corpus this site is built on — calls from the EU Funding & Tenders Portal, CORDIS, Spain's BDNS and the BOE, normalised into one schema. The machine-readable contract is an OpenAPI 3.1 document; it is generated from the same constants the API validates against, so it never describes a parameter the endpoint would reject.

Two promises worth reading before you build on it

Only published calls are ever returned. Records withheld under the SNPSAP aviso legal — an organisation that is a natural person, for instance — are absent from every response, and there is no parameter to include them.

Nothing about a deadline is invented. deadline is the closing day the source published. deadline_time is filled in only when the source stated a time, and is null otherwise — never midnight, because a midnight nobody published would sort and filter as though somebody had. status is the status as it reads today: a call whose stated deadline has passed is reported closed even when its source still calls it open.

Getting started

No credential needed:

curl 'https://quiescence.eu/funding/api/v1/search?q=hydrogen&status=open&per_page=5'

With a key, for higher limits:

curl -H 'X-API-Key: fnd_…' \
     'https://quiescence.eu/funding/api/v1/search?country=ES&sort=deadline'

Issue a key on your account page. It is shown once: only a hash is stored, so it cannot be recovered or re-displayed — if you lose one, revoke it and issue another. Send it as the X-API-Key header and never as a query parameter, because URLs reach access logs, Referer headers and browser history.

Tiers

TierPer minutePer dayHow to get it
anonymous 60 — Send no credential. Limited by IP.
basic 120 1,000 Any signed-in account can issue a key.
pro 600 25,000 A key owned by an account with an active subscription.

The tier is decided per request from the live subscription, not stored on the key — so an upgrade applies immediately and a lapse downgrades immediately. Anonymous callers have no daily quota on purpose: a daily cap on an IP is a cap on everyone behind one network, and the first people it would cut off are a university or a ministry.

Limits, and what to do when you hit them

Every response carries its own accounting:

X-API-Tier
The tier this request was served under.
X-RateLimit-Limit
Requests allowed per minute.
X-RateLimit-Remaining
Requests left in the current minute.
X-Quota-Limit
Daily allowance. Absent for anonymous callers, who have none.
X-Quota-Remaining
Calls left today, with this one already counted.
X-Quota-Reset
Seconds until the daily window rolls.

Both limits answer with 429 and a Retry-After in seconds, which is authoritative — prefer it to your own backoff. The two are distinguishable by the error field: rate_limited means you are going too fast right now and Retry-After is a few seconds; quota_exceeded means the day's allowance is gone and Retry-After counts down to 00:00 UTC, when the window rolls.

Nothing resets a counter at that moment — tomorrow's calls are simply counted against tomorrow's date — so the reset needs no scheduled job and cannot be delayed by one failing.

Errors

Every error has the same shape. Branch on error, which is stable; message is for humans and may change.

{"error": "quota_exceeded", "message": "Daily quota reached for this API key. It resets at 00:00 UTC."}
bad_request (400)
A parameter failed validation; the message names which.
invalid_key (401)
The key is not recognised — usually a truncated copy.
revoked_key (401)
The key was valid and has been revoked. Issue a new one.
subscription_required (403)
The endpoint is part of the paid plan.
rate_limited (429)
Too fast. Wait Retry-After seconds.
quota_exceeded (429)
Day's allowance used. Resets at 00:00 UTC.

Endpoints

GET /search

Parameters: q, country, status (