# Foresight API > Full machine-readable reference for agents using Creative Foresight economic, demographic, financial, and derived `cf:*` indicators. Base URL: https://api.creativeforesight.io ## Links - API root: https://api.creativeforesight.io/ - OpenAPI 3.1: https://api.creativeforesight.io/openapi.json - Short llms.txt: https://api.creativeforesight.io/llms.txt - Docs: https://docs.creativeforesight.io - Pricing: https://docs.creativeforesight.io/guides/pricing - Use from an AI agent (Claude, OpenAI, LangChain tool-use snippets): https://docs.creativeforesight.io/guides/agents - Checkout (Developer plan): https://api.creativeforesight.io/api/billing/checkout?plan=developer - Checkout (Pro plan): https://api.creativeforesight.io/api/billing/checkout?plan=professional - Changelog: https://docs.creativeforesight.io/changelog - MCP endpoint: https://api.creativeforesight.io/api/mcp ## Authentication - API key: send `Authorization: Bearer cf_live_...` or `X-API-Key: cf_live_...`. - Anonymous x402: call a paid observation, insight, signal, panel, ask, flow, or public briefing endpoint without a key, read the HTTP 402 x402 v2 `resource`, `accepts`, and `extensions.bazaar` payment requirements, create a payment, then retry with `X-PAYMENT`. - Catalog endpoints are free and anonymous. - Self-serve free-tier keys: `POST /v1/signup` with JSON `{ "email": "you@example.com" }`; the raw `cf_live_` key is returned exactly once. - Premium indicators and signals require an unrestricted key, a key granting `creative-foresight`, or x402 on payable endpoints. - Standard x402 observation/latest price: $0.01 per request. - Creative Foresight original `cf:*` x402 observation/latest price: $0.05 per request. - Creative Foresight signals x402 price: $0.05 per request. - Insights x402 price: same as the underlying indicator ($0.01 standard, $0.05 for `cf:*`). - Flows x402 price: $0.01 per request. - Batch latest x402 price: `GET /v1/observations/latest?indicators=A,B,C` is a flat $0.01 per request, up to 20 indicators. - Concept aliases x402 price: same as the resolved series. For example, `indicator=population` costs $0.01; a concept such as `misery_index` that resolves to a `cf:*` premium series costs $0.05. ## Endpoint Reference - `GET /`: JSON discovery index with `name`, `docs`, `openapi`, `mcp`, `llms`, `pricing`, `checkout` (the Developer plan) and `checkout_plans` (one checkout URL per plan). - `GET /api/health`: service health. - `GET /openapi.json`: OpenAPI 3.1 contract. - `GET /llms.txt`: compact agent discovery file. - `GET /llms-full.txt`: this full agent discovery file. - `GET /changelog.md`: public API changelog. - `POST /v1/signup`: create a free-tier API key. Per-IP limit is 5 keys per day; successful responses include `key`, `key_hint`, `rate_limit_per_minute: 60`, and `docs_url`. Optional body fields: `source` (free-text "where did you find us", up to 120 characters) and `utm_source`, `utm_medium`, `utm_campaign` (each up to 120 characters); they are used only for anonymous attribution and are never stored with the key. - `POST /v1/keys/rotate`: bearer-authenticated. Replaces the secret of the calling key in place; the old key fails authentication immediately, and plan, rate limit, usage, and billing carry over. Free keys receive `data.key` in the response (`delivery: "response"`); keys on a paid subscription never do — the new key is emailed to the Stripe billing address (`delivery: "email"`, masked `delivered_to`). Limited to 5 rotations per key per 24 hours. Not metered, and allowed even when a free key has used its monthly quota. - `POST /v1/keys/revoke`: bearer-authenticated. Permanently revokes the calling key. A key that pays for an active subscription returns `409 SUBSCRIPTION_ACTIVE` unless the body is `{"cancel_subscription": true}`, which cancels the subscription immediately (no refund of the current month; overage already used is invoiced) and then revokes the key. - `POST /v1/keys/recover`: public. Body `{"email": "billing@example.com"}`. If the address is the billing email of an active or past-due subscription, a single-use `cfr_` token valid for 30 minutes is emailed to it; the answer is the same `202` either way. Free keys are not recoverable — sign up again. 10 requests per client IP per day, 3 tokens per key per hour. - `POST /v1/keys/recover/confirm`: public. Body `{"token": "cfr_..."}`. Consumes the token, replaces the key's secret, and emails the new key to the billing address; the response carries only hints. Invalid, expired, or reused tokens return `400`. - `GET /v1/sources`: data sources with provider metadata and indicator counts. - `GET /v1/regions`: available regions. Use `type=county`, `state`, `country`, or other supported region types to filter. - `GET /v1/indicators`: indicator catalog with `category`, `subcategory`, and `access_tier`. Query params include `source`, `category`, `frequency`, `search`, `limit`, `offset`, and `include_inactive`. - `GET /v1/indicators/{code}`: indicator detail by code with `access_tier`. Optional `source` disambiguates duplicate provider codes. - CONCEPTS (all read endpoints): plain-word codes — `population`, `gdp`, `median_income`, `median_home_value`, `unemployment_rate`, `labor_force`, `employed` — work anywhere an indicator code does. Exact indicator codes always win (concepts never intercept a real code); a concept requires `region` and resolves per region kind (e.g. `gdp` for the US answers from FRED quarterly, other countries from World Bank annual); the chosen series is always disclosed in `meta.concept = {code, resolved_indicator, source}`. A concept not curated for the requested region kind returns a plain-language 404 naming the closest available level; series being prepared follow the standard 202/Retry-After semantics. DERIVED concepts (e.g. `employment_rate` = employed ÷ labor force × 100) are computed by Creative Foresight per place and disclose every input series in `meta.concept.inputs`; a missing ingredient refuses plainly naming the blocking input. `/v1/ask` resolves natural-language questions to concepts first, deterministically — identical questions cite identical series. - `GET /v1/observations`: observations for `indicator` and optional `region`, `start_date`, `end_date`, `limit`, `offset`, `order`, `include_revisions`, and `source`. Requires an API key or x402 payment. Optional `transform=yoy|mom|qoq|index:YYYY-MM-DD|log` applies a query-time transform: percent changes use calendar-correct comparators read from the full series, even before the returned page or `start_date` (a row yields `null` only when its comparator is missing from the series), `index:` rebases so the base date equals 100, `log` is the natural log (non-positive values become `null`), the response `meta.unit` updates to match, and `meta.transform` echoes what was applied. `transform` cannot combine with `include_revisions`; `yoy` is unavailable on daily series at native frequency — add `frequency=monthly` to get monthly yoy from daily data. Optional `frequency=monthly|quarterly|annual` downsamples to calendar buckets before any transform, with `resample_method=mean|last|sum` (default mean; mean matches the common aggregation default). Resampled rows are synthetic aggregates `{period_start, period_end, period_type, value}` labeled by bucket start date; `limit`, `offset` and `meta.total` count output buckets over the whole requested range, each bucket aggregates every source row in it, and the series' newest bucket is dropped while still incomplete rather than served as if complete — `meta.resample` reports the method, source/target frequencies, and that drop. - L402 (Lightning): every paid route's 402 carries, alongside the x402 `accepts`, a `WWW-Authenticate: L402 macaroon="…", invoice="…"` challenge. Pay the bolt11 invoice from any Lightning wallet, take the payment preimage, and retry the identical request with `Authorization: L402 :`. The macaroon is scope-bound to the requested indicator and expires 10 minutes after issuance; verification is instant and requires no account. Either rail settles a request — use whichever your stack speaks. - `GET /v1/flows`: directed origin-to-destination flow rows for a region filter. Params: at least one of `origin` or `destination` is required; optional `measure`, `period`, and `limit`. When `period` is omitted, the latest available `period_start` for the filters is used and reported in `meta.period`. Requires $0.01 paid x402 request or an API key. - `GET /v1/panel`: up to 10 indicators on one aligned date grid in a single call — `{dates, series: {CODE: [...]}, meta: {units, alignment, region, frequency}}`. Params: required `indicators=A,B,C`, optional `region`, `frequency`, `start_date`, `end_date`, `missing=drop`. Same-frequency panels align at native frequency; mixed-frequency panels resample finer series to the coarsest frequency (or to an explicit `frequency=monthly|quarterly|annual`) with `resample_method=mean|last|sum` (default mean) — `meta.resample` names each resampled series' native frequency. Weekly-only panels must pass `frequency=monthly` or coarser. `missing=drop` keeps dates present in every series; `missing=ffill` uses the union of dates and carries each series' last value forward (leading gaps stay null). Grid capacity is 5,000 points; series longer than the window capacity return 400 asking for a narrower date range. A panel containing any `cf:*` series requires premium access. $0.05 per paid x402 request or a premium API key. - `GET /v1/observations/latest`: latest observation for `indicator` and optional `region` and `source`, or batch latest with `indicators=A,B,C` up to 20 codes returning `{data, errors}`. Requires an API key or x402 payment. - `GET /v1/insights`: deterministic computed facts plus active signals for one indicator. Params include required `indicator` and optional `region`, `source`, and `window=all|Nd|Nm|Ny` (default `all`). Facts include `humanTemplate`, typed `params`, `text`, and `salience` from 0..1; signal payloads include strength, direction, evidence, `text`, and shared glyph/label/tone vocabulary metadata. `text` is a server-rendered, shareable plain-spoken sentence, guaranteed non-null for every active indicator (display-metadata coverage is 100% and monitored daily). Uses the same `access_tier` rule as observations. - `GET /v1/ask`: a natural-language question in, a grounded answer out. Params: required `q` (1-500 chars), optional `region` (FIPS hint) and `window=all|Nd|Nm|Ny`. The response carries `answer` prose plus a machine-readable trace: `citations` (the tool calls actually executed, each with args and a payload summary), `resolved` (indicators/regions/window the question mapped to), `grounded` (false if any number in the prose failed verification against cited payloads), and `truncated` (true when per-request ceilings ended the work early — narrow the scope and ask again). Questions with no catalog coverage return a free `no_coverage` response — on the x402 path no 402 challenge is issued at all. Covered questions are $0.25 per paid x402 ask or any API key; `depth=briefing` runs a deeper pass on a premium model for $1.50 (invalid depth is a free 400; uncovered questions are free at any depth) and `meta.depth` echoes what ran. Statistics are computed by the deterministic facts layer, never by the model; every citation's args replay against `/v1/observations`, `/v1/insights`, and `/v1/signals/active` for independent verification. - `GET /v1/briefings/public`: free catalog of curated Foresight briefings — slug, name, question, cadence, last_run_at. - `GET /v1/briefings/public/{slug}`: the latest successful run of a curated briefing — the stored grounded answer with its full citation trace. $0.10 per paid x402 read or a premium API key. Unknown, private, or never-run slugs are free 404s — you don't pay for nothing. - `GET /v1/briefings`: saved scheduled ask briefings owned by the calling API key. - `POST /v1/briefings`: create a saved ask briefing (premium API key). Body: required `name` (1-120 chars), `question` (1-500 chars), and `cadence` (`weekly`; `daily` is not included in this tier), optional `region` and `window=all|Nd|Nm|Ny`. - `GET /v1/briefings/{id}`: a saved briefing and its latest run. - `DELETE /v1/briefings/{id}`: delete a saved briefing. - `GET /v1/briefings/{id}/runs`: run history for a saved briefing; optional `limit`. - `GET /v1/signals/active`: active Creative Foresight signal intervals. Filters include repeatable or comma-separated `indicator`, `region`, `type`, `strength`, and `limit`. Requires $0.05 paid x402 request or a premium API key. - `GET /v1/signals`: signal interval history. Supports active filters plus `active`, `from`, `to`, and `cursor`. Requires $0.05 paid x402 request or a premium API key. - `GET /v1/ping`: validate bearer API key connectivity; returns 200 for a working key. - `POST /api/mcp`: Streamable HTTP MCP endpoint exposing `search_indicators`, `list_sources`, `list_regions`, `get_observations`, `get_latest`, `get_insights`, `get_active_signals`, and `ask`. ## Indicator Taxonomy and Access - `category` and `subcategory` are taxonomy only. - Top-level categories are `macro`, `labor`, `prices`, `markets`, `housing`, `government-finance`, `demographics`, `business`, `energy`, `crypto`, `health`, `environment`, and `education`. - `access_tier` is `free` or `premium`. Premium requires an unrestricted key, a key granting `creative-foresight`, or x402 on payable endpoints. - Creative Foresight original derived series use `cf:` prefixes and `access_tier: "premium"`; examples include `cf:labor_composite`. ## Response Semantics - Successful API responses use `{ "data": ..., "meta": ... }`. - Error responses use `{ "error": { "code": "...", "message": "...", "details": ... } }`. - Observation rows include period, value, unit, source, revision, and preliminary status. - Signal rows include indicator metadata, region, type, minimum strength filter semantics, interval timestamps, detector evidence, `text`, and shared vocabulary glyph/label/tone metadata. Direction flips close open intervals, so `since ` in prose is the current run's start. - A `/v1/observations` or `/v1/observations/latest` request for an indicator or region we do not offer returns 404 `RESOURCE_NOT_FOUND`. - Some observation requests return `202` with a `Retry-After` header and body `{ "status": "provisioning", "indicator": "...", "region": "...", "retry_after_seconds": N, "request_ref": "..." }`: the data is being prepared for you. Wait `Retry-After` seconds, then retry. Treat continued 202s as still-preparing and keep retrying with the given delay for up to a few minutes; a request that keeps returning 404 is for a series we do not offer. - The 202 body's `indicator` field is the canonical catalog code the data will be served under. It can differ from the code you asked with (some sources accept friendly aliases); if it does, retry using the code from the body. ## Worked Examples List data sources: ```bash curl "https://api.creativeforesight.io/v1/sources" ``` Ask in plain language (grounded answer + citation trace): ```bash curl "https://api.creativeforesight.io/v1/ask?q=How+has+unemployment+in+Williamson+County,+Texas+trended+over+the+past+two+years" \ -H "Authorization: Bearer cf_live_REPLACE_ME" # Response shape: {"answer":"...prose...","citations":[{"tool":"get_insights","args":{...},"summary":"..."}],"resolved":{"indicators":[...],"regions":[...],"window":"all"},"grounded":true,"truncated":false,"status":"ok","meta":{...}} # No coverage -> {"answer":null,"status":"no_coverage","message":"No Foresight data covers that question.",...} and the request is free. ``` Search the catalog: ```bash curl "https://api.creativeforesight.io/v1/indicators?search=unemployment&limit=5" ``` Fetch observations with an API key: ```bash curl "https://api.creativeforesight.io/v1/observations?indicator=UNRATE®ion=US&limit=12" \ -H "Authorization: Bearer cf_live_REPLACE_ME" ``` Fetch a premium Creative Foresight series: ```bash curl "https://api.creativeforesight.io/v1/observations/latest?indicator=cf%3Alabor_composite®ion=47187" \ -H "Authorization: Bearer cf_live_REPLACE_ME" ``` Fetch latest observations in a batch: ```text curl "https://api.creativeforesight.io/v1/observations/latest?indicators=UNRATE,INDPRO,PCEPILFE®ion=US" \ -H "Authorization: Bearer cf_live_REPLACE_ME" # Response shape: {"data":[...latest observations...],"errors":[...per-indicator errors...]} ``` Fetch deterministic facts plus active signals: ```bash curl "https://api.creativeforesight.io/v1/insights?indicator=UNRATE®ion=US&window=5y" \ -H "Authorization: Bearer cf_live_REPLACE_ME" # Response shape: {"facts":[{"humanTemplate":"...","params":{...},"text":"...","salience":0.82}],"signals":[{"strength":"strong","direction":"up","text":"...","vocabulary":{"glyph":"trending-up","label":"Worsening faster","tone":"negative"}}],"meta":{...}} # UNRATE is lower-is-better, so an up-acceleration renders label "Worsening faster" with negative tone. ``` Fetch active premium signals: ```bash curl "https://api.creativeforesight.io/v1/signals/active?indicator=UNRATE&strength=strong" \ -H "Authorization: Bearer cf_live_REPLACE_ME" ``` x402 402 to pay to retry flow plus MCP discovery: ```bash curl -i "https://api.creativeforesight.io/v1/observations/latest?indicator=unemployment_rate®ion=47187" # HTTP 402 includes x402Version: 2, top-level resource, accepts payment requirements, and extensions.bazaar discovery metadata. # Create a payment for one accepts entry with your x402 wallet, then retry: curl "https://api.creativeforesight.io/v1/observations/latest?indicator=unemployment_rate®ion=47187" \ -H "X-PAYMENT: BASE64_PAYMENT_PAYLOAD" # MCP Streamable HTTP initialization uses the same host: curl -N "https://api.creativeforesight.io/api/mcp" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer cf_live_REPLACE_ME" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' ``` ## MCP Notes The MCP server is hosted over Streamable HTTP at `POST /api/mcp`. Catalog tools are available without auth. Observation, insight, and active signal tools return data with the same pricing and entitlement model as the REST API when called with an API key.