The Future Demand platform runs in two environments. Always build against
staging first. Production access is granted once your integration has
passed a smoke test with us.
There are two API surfaces with distinct hosts:
Client API (Lookout + Wave)
| Environment | Base URL |
|---|
| Staging | https://client-api.stg.future-demand.com/api/v3 |
| Production | https://client-api.prd.future-demand.com/api/v3 |
Affinity (on-site recommendations)
| Environment | Base URL |
|---|
| Staging | https://fd-recommender.stg.future-demand.com |
| Production | https://fd-recommender.prd.future-demand.com |
Affinity is its own product — the recommendations service for partner
websites and apps. See Affinity overview.
It uses a separate credential from the Client API; a token issued
for one will not work against the other.
The base URL has three parts: the host (client-api.<env>.future-demand.com),
the /api prefix (always present), and the /v3 version (always
present at this major version).
Path conventions in this doc
Endpoints in this documentation are written without the base URL. A path
like GET /events/ is shorthand for:
GET https://client-api.stg.future-demand.com/api/v3/events/
The exception is a handful of endpoints that hit the API host but without
the /v3 prefix — POST /media is the notable case. These are explicitly
flagged in the relevant guides.
Driving the base URL from config
const BASE_URL =
process.env.FD_BASE_URL ??
"https://client-api.stg.future-demand.com/api/v3";
const ACCESS_TOKEN = process.env.FD_ACCESS_TOKEN; // see /authentication
const PARTNER_ID = process.env.FD_PARTNER_ID;
For a production deployment, also pin:
FD_PARTNER_ID — the partner you’re acting as (sent as X-Preferred-Partner-Id).
- Your refresh token — stored server-side, used to mint short-lived
access tokens. See Token refresh.
Local mock server
The reference webapp (fd-client-webapp) ships a small mock server for
offline development. It is a partial mock, not a faithful API replica —
useful for wiring up UI, not for validating contracts.
If you have access to the reference webapp repository:
yarn mock-api # starts the mock at http://localhost:5001
export FD_BASE_URL=http://localhost:5001/v2 # note: port 5001, /v2 paths, NO /api prefix
The mock listens on port 5001 and serves /v2/... routes without an
/api prefix — different from the production base URL
(client-api.{env}.future-demand.com/api/v3). Don’t assume the mock
mirrors production paths.
What’s actually mocked (approximate):
| Endpoint family | Coverage |
|---|
/auth/* | Partial |
/events/* | Mostly implemented |
/campaigns/* | Partial |
/messages/* | Only GET /messages/partner |
GET /features, GET /statistics, GET /integrations/facebook/ads/stats, POST /media | Implemented (undocumented) |
GET /partners/, /notifications/* | Not implemented |
Treat the mock as a convenience for front-end wiring; test real behaviour
against staging.
Health check
Each environment exposes the same status endpoint:
curl -s https://client-api.stg.future-demand.com/api/v3/status/
# => { "status": "ok", "datetime": "2026-05-20T14:31:02Z" }
Use this for CI smoke tests and uptime monitors. It does not require
authentication.
Regions and data residency
All environments are hosted in eu-central-1 (Frankfurt). If you need a
different region for compliance reasons, talk to your account contact —
we can provision a region-pinned partner.
CORS
The API permits cross-origin requests from * only on GET /status/. All
authenticated endpoints reject browser CORS, by design — your refresh token
must not be exposed to a browser. Proxy authenticated calls through your
own backend, or use a short-lived access token issued from your origin.
See Authentication for the trade-off and
Your First Integration for the proxy pattern.
Versioning
- The version prefix in the URL (
/v3) is the only version selector. We
do not honour Accept-Version headers.
- Breaking changes ship as
/v4 and are announced ≥ 90 days in advance via
the changelog and a direct email to integrators.
- Within a major version we only add fields and endpoints; we never remove
or rename existing ones. Build your clients to ignore unknown fields.