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 (