Amba

Config

Per-user evaluated remote config — segment + percentage rollout, ETag-aware.

/client/config is the single evaluation endpoint for remote config. Authenticated callers get per-segment + percentage-rollout values; anonymous callers get defaults only. Responses are cacheable via ETag / If-None-Match; cache control is private to prevent multi-tenant leakage through shared proxies.

Endpoints

MethodPathDescription
GET/client/configEvaluated config map. Accepts only X-Api-Key (session token optional).

GET /client/config

Request

GET /client/config
X-Api-Key: amb_client_ck_xxx
Authorization: Bearer <session-token>    (optional — anonymous callers get defaults)
If-None-Match: "<prior-etag>"            (optional)

Response 200

{
  "data": {
    "my_feature_flag": true,
    "paywall_price": 9.99,
    "promo_copy": { "headline": "Spring sale", "discount": 0.2 }
  }
}

Each value comes back as its declared type — a boolean is a JSON true/false, a number is a JSON number, and a json config is a parsed object/array. You don't parse or cast on the client; config.promo_copy.headline works directly.

Typed values

Every config carries a value_type of string, number, boolean, or json, set when the config is authored. The server coerces the resolved value to that declared type before it serializes the response, so a value authored as a string of JSON (a common mistake) still arrives as the right type — no client release required. Coercion is forgiving: a value that's already the right shape passes through untouched, and a value that can't be coerced (malformed JSON, a non-numeric string typed as number) is returned as-is rather than failing the whole fetch.

value_typeYou receive
stringA JSON string.
numberA JSON number.
booleanA JSON true / false.
jsonA parsed object / array / any value.

Headers:

ETag: "<version_hash>[:<user_id>:<segments_hash>]"
Cache-Control: private, max-age=60        (authenticated)
Cache-Control: private, max-age=300       (anonymous)
Vary: Authorization

Response 304

Returned when If-None-Match matches the current ETag. The body is empty.

ETag composition

  • Anonymous: "<version_hash>" — singleton config_versions.version_hash.
  • Authenticated: "<version_hash>:<appUserId>:<sha256(sorted-segments)[:16]>" — invalidates automatically on segment membership changes.

Per-segment + percentage variants

A config isn't a single value — it can carry a conditions array, evaluated in order at read time, where each entry overrides the value for a slice of your users:

{
  "key": "paywall_price",
  "value_type": "number",
  "default_value": 9.99,
  "conditions": [
    { "segment_id": "<whales-segment-id>", "value": 14.99 },
    { "percentage": 10, "value": 4.99 }
  ]
}

Each condition has an optional segment_id, an optional percentage (0–100), and the value to return when it matches. The first condition that matches the calling user wins; if none match, default_value is returned. All variant values are coerced to the config's value_type, exactly like the default. The evaluation is per-user and happens server-side, so the client receives a single resolved value with no branching logic.

The per-condition ladder (in order):

  1. If segment_id is set, the user must be a member of that segment.
  2. If percentage is set and < 100, the user is included only when hash(appUserId|key) % 100 < percentage — a stable, deterministic bucket, so a user stays on the same side of a rollout across requests.
  3. First matching condition wins. Otherwise default_value is returned.

A condition with neither segment_id nor percentage matches everyone that reaches it — useful as a catch-all rung below more specific conditions. A condition with only percentage is a pure rollout gate; one with only segment_id is a pure per-segment override.

Errors

  • 500 FETCH_FAILED.

Try it:

GET/client/config
client auth
curl -X GET 'https://api.amba.dev/v1/client/config'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

Curl:

curl -X GET '${BASE_URL}/client/config' \
  -H 'X-Api-Key: ${CLIENT_API_KEY}' \
  -H 'Authorization: Bearer ${SESSION_TOKEN}'

On this page