Developer platform · SDK API v1

SDK API explorer

Every route the ContentFlow SDKs call, with request and response examples you can send against your test key. New to ContentFlow? Read How ContentFlow works first for the call order and what each step depends on.

Import into Postman, Insomnia or a code generator: OpenAPI JSON · YAML

Base URL
https://api.contentflow.click/sdk/v1
Key header
X-CF-Key: <workspaceId>_cfpk…
Device header
X-CF-Device: explorer-test-1 (made-up id)
Environments
test or live, reported in the X-CF-Env response header

Start here

  1. Get your test key Portal → Developers → Test mode (“Your test key”). It is created for you and looks like <workspaceId>_cfpk…. The Open in API explorer button there brings you here with the key already authorized.
  2. Authorize Press Authorize in the reference below and paste the key into Publishable key. The explorer checks it against the API straight away. It's kept only for this tab.
  3. Pick a device id Device-scoped calls need X-CF-Device. Use something like explorer-test-1, never a real customer's id.
  4. Send a request Open an operation, edit the example and press Execute. Follow the test flow for the right order.

This explorer takes the publishable test key (<workspaceId>_cfpk…, from the portal Developers page). A secret API key (pk_test_…) reaches the same routes but must stay out of browsers; the explorer warns if you paste one. Write and read keys are server-only and never used here. Every key and header: Keys in the REST guide.

How the explorer keeps you safe
  • Live keys ask first. A live key (a derived _app key, or any key the API reports as live in X-CF-Env) creates real devices and events; the explorer asks you to confirm before sending.
  • Erasure asks first. DELETE /identify permanently erases a device's data; you confirm before it's sent.
  • Write keys never leave your server. /cards/* takes a write key; the explorer shows the curl to run from your server or CI instead of sending it.
  • Nothing is stored. Keys are not saved between visits. Test-key traffic is kept apart from live analytics.

Test flow: one device, end to end 7 calls

Run these in order with the same device id. Each step depends on the one before it; the expect column is what a pass looks like.

#CallSendExpect
1POST /identifyconsent: true, a test userId200, consent: true, results.identity.status identified
2GET /sync?locale=en200 with blocks[]; again with the returned ETag in If-None-Match → 304
3GET /strings?locale=ar200, strings in Arabic where translated
4POST /eventsThe example batch (an impression and a purchase)202, accepted = events sent, empty dropReasons
5POST /consentchannels: {push: true}; username = the step-1 userId (or omit it)200; another username → 403 USER_MISMATCH
6POST /register-pushA dummy token, platform: "android", provider: "fcm"200, registered: true
7DELETE /identifyClean up the test device200, localWipeSafe: true

Negative checks worth running: step 4 before step 1 with a fresh device id → 202 with dropReasons.device_not_identified; step 1 with consent: false then step 4 → consent_not_granted; any call without a key → 401 MISSING_SDK_KEY.

Responses every operation can return 401 · 429 · 502

These are documented once here and folded away inside each operation (use Show common responses to see them in place).

StatusCodeMeaningWhat to do
401MISSING_SDK_KEY / INVALID_SDK_KEYNo key, or a malformed or revoked oneSend X-CF-Key; check the key in the portal
429SDK_RATE_LIMIT_EXCEEDEDWorkspace over 1,000 requests/min (burst 100)Wait Retry-After seconds and retry
502UPSTREAM_UNAVAILABLEA service behind the gateway is briefly unreachable; retryable: trueRetry after Retry-After (5 s)

Error body: {"success": false, "error": "…", "code": "…"}. A 202 on /events or /location can still have dropped items: always read dropReasons. More in the REST guide.

Loading the API reference…

Checked against the gateway source: a CI check fails if a gateway route is added or removed without updating this reference.