Integrate with QuickLookup
Use REST for applications and the MCP endpoint for compatible agent clients. Both enforce the same bearer identity, catalogue visibility, saved-context ownership, paging, and delivery code.
REST clients
- List visible services with
GET /v1/catalog/services. - Cache the selected detail response using its private
ETag. - Build controls from
contract.inputs,inputAlternatives, andchoices. - Send a returned example to
queryUrl, then change only the required values. - Page by returning
nextCursorunchanged.
Do not hard-code database relations or FDW parameters. Treat service and contract revisions as part of the response provenance.
Access window
A caller sees only the stretch of time its plan allows. That stretch is a sliding window from now(), never a fixed date. The token names it as offsets:
| claim | meaning |
|---|---|
accessBack |
whole days before now the caller may see; null = unlimited |
accessAhead |
whole days after now; null = unlimited |
accessCountries |
optional ISO 3166-1 alpha-2 codes |
The window is [now − accessBack days, now + accessAhead days), computed afresh on every
request, so it moves with the clock. No token, API key or response carries a fixed window. An
API key's only date is its own expiry.
Every read is cut to the window, whatever the request asks for:
- Observations and aggregates: only points inside the window count.
- Events: an event is returned whole if it overlaps the window, and never cut. One wholly
outside the window is never returned.
- Cursors: a cursor is a position, not a range. Page 2 is cut exactly like page 1.
- Partly outside: a request that reaches past the window is answered inside it. The
response carries accessWindow: the offsets back and ahead, from/to (where the
window reached at the moment of this answer), and narrowed: true. It also carries the header
QL-Access-Window: back=365; ahead=7, so a client can say "limited to your plan".
- Was anything held back? narrowed says only that the request reached past the window.
The first page of a narrowed answer also carries accessWindow.withheld: {before, after}:
true when QuickLookup holds something on that side, false when it holds nothing there,
null when it cannot tell from what it holds: that stretch of an on-demand source is not
fully mirrored (it is never fetched just to find out). Say "there is more beyond your plan"
only when it is true.
- Wholly outside: a query of one service (/v1/services/{gid}/query, /v1/data/query,
/v1/events/query) with nothing inside the window is refused with 403
period_not_permitted, and the error names the offsets. A day (POST /v1/context/day) is
still answered, and such a section reads not_permitted. A nearby search is still answered
too, and names each feed outside the window in feedsSkipped with code:
period_not_permitted.
- Calendars (school calendars, holidays, weekends, seasons, day archetypes, celestial) are
published wholeOnEveryTier and are never cut.
- The figure in force at the window's start: a data service published latestOnEveryTier
(every Trading Economics service: indicators, currencies, commodities, bonds, indexes) also
answers a first page the window cut from BELOW with accessWindow.latest, the series'
newest point strictly before accessWindow.from: the value that stands when the window
opens. A currency has no fixing on a weekend, so a window opening on a Sunday holds Monday's
rate and nothing that says Friday's close still stood; latest is that close. It is never
among the items, so the history stays cut: use it for a day with no point on or before it,
and draw the history as limited to your plan. It is attached whether or not the window
holds points of its own, and absent when the read was not cut from below (its from was
inside the window), on later pages, and for an aggregated ($apply) read.
A product site's token must carry both offsets. One that does not is refused
(403 access_window_missing, QUICKLOOKUP_ACCESS_WINDOW_REQUIRED) and counted on
quicklookup_access_window_missing_total.
MCP clients
POST https://quicklookup.com/mcp, with your API key as the bearer token, is a sessionless, read-only MCP endpoint. Authenticate every request with the same bearer token used by REST.
It speaks protocol version 2026-07-28, and also 2025-11-25 and 2025-06-18, so a key works from any current MCP client:
- On
2026-07-28: every request names the version inparams._metaand in theMCP-Protocol-Versionheader. - On the earlier versions: the client opens with
initialize, and is answered with the version it asked for, or with2026-07-28if it asked for one not listed. Its later requests name that version in theMCP-Protocol-Versionheader. No session is kept.
Caching: answers that are the same for everyone may be cached privately. The handshake and
discovery keep for 60 seconds, the tool list for an hour (ttlMs/cacheScope in the result,
and Cache-Control). A tool's answer, a ping and an error are no-store.
The endpoint exposes ten read-only tools:
| Tool | Use |
|---|---|
list_data_services |
Search access-filtered service summaries. |
get_data_service |
Inspect one contract, its alternatives, limits, and examples. |
query_data_service |
Run the inspected service and continue with its cursor. |
search_nearby_events |
Search occurrences across every visible event feed near a runtime location. |
list_time_series_families |
Find each semantic time series once, with source/resolution/quality filters. |
get_time_series_family |
Inspect authorized variants and choose a concrete recommendation. |
list_saved_context |
Search account and personal context, optionally by context type. |
get_saved_context |
Inspect one reusable selection and its health. |
resolve_saved_context |
Resolve data-service or time-series context into catalogue items. |
query_saved_event_context |
Apply saved event filters to a runtime period and optional location. |
Start with server/discover. Send the protocol version in both MCP-Protocol-Version and
the request _meta; send Mcp-Method for every call and Mcp-Name for tools/call.
Use the returned tool schemas rather than duplicating them in client code.
When saved context exists, start with list_saved_context. Use its contextGid with
get_saved_context, then either resolve_saved_context for data-service/time-series context
or query_saved_event_context for event context. Event context always needs runtime from
and to; time and location are not stored in the context definition.
For new time-series discovery, use list_time_series_families, then
get_time_series_family. The family detail contains the authorized variants, selection
reasons, and a concrete recommended queryUrl; pass that concrete service to
query_data_service. This preserves the same family-first presentation as the web catalogue.
query_data_service also takes $apply, the OData aggregation expression the REST query
accepts, and answers with the same groups (Aggregate).
What to do at a place. Search list_data_services for "activity rating" and query it
with lat, lon, the day (from/to), and optionally at (the moment), available_min
(the time the caller has) and activity. Every one of 43 activities comes back in one of
three states: rated 1–100; not possible, rated 0 with its reason; or unavailable, with a
null rating where a source it needs does not cover the place (missing names it) — show
that apart from 0. Each carries up to ten ranked options: places or events,
the chosen first, each with its own rating, factors, travel, opening, fee and
shared_with. The activities are answered together, so one place is not the answer to
everything; facility_tags names the OpenStreetMap kinds that serve each activity. An
option's factors.weather is absent when its weather was not read: never read it as good
weather (Place and day: Activities).
query_data_service and search_nearby_events wait for their sources by default, which can
take seconds for data nobody has asked about yet. Pass "respondAsync": true to be answered
at once instead: what is ready comes back, and anything still being fetched is named under
pending (or feedsPending) with retryAfterMs. Call the tool again with the same arguments
after that for the rest — the same behaviour REST gives Prefer: respond-async
(Answer now, fill in later).
MCP tools are annotated as read-only, non-destructive, and idempotent. Create, replace, and archive context through REST or the authenticated API console; agent clients use the same context without gaining mutation authority.
Connect an MCP client to https://quicklookup.com/mcp with your API key as the bearer token.
Semantic consumers
GET /v1/semantic/manifest returns the published time-series and event definitions visible
to the caller. It is intended for semantic engines that need relations, contracts,
predicates, mappings, and custom aggregations.
The response is private. Cache it with the returned ETag or remember
manifestRevision; send If-None-Match or sinceRevision on the next request. A 304
means the visible manifest has not changed.
Browser security
The documentation explorer stores its token in sessionStorage, limits requests to the
same origin, and discards the token when the tab session ends or you select Change
token. Production applications should keep tokens out of URLs, logs, persistent browser
storage, and shared error reports.