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)

EnvironmentBase URL
Staginghttps://client-api.stg.future-demand.com/api/v3
Productionhttps://client-api.prd.future-demand.com/api/v3

Affinity (on-site recommendations)

EnvironmentBase URL
Staginghttps://fd-recommender.stg.future-demand.com
Productionhttps://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 familyCoverage
/auth/*Partial
/events/*Mostly implemented
/campaigns/*Partial
/messages/*Only GET /messages/partner
GET /features, GET /statistics, GET /integrations/facebook/ads/stats, POST /mediaImplemented (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.