// wiki / http-rest

HTTP & REST API

HTTP endpoints for creating, querying, updating, and deleting feature flags from your backend, plus ready-to-run request examples in 11 languages. Evaluation and management requests use scoped credentials issued under Management Keys. For .NET, an official SDK package wraps all of this.

Download the HTTP Postman collection

Twenty-seven ready-to-run requests covering the whole API over HTTP, each with response tests, plus an environment template whose values are left blank for you to fill in. Connecting to Maxlona takes one paste of your Management Key.

Download Maxlona HTTP Collection
In the zip
  • Maxlona HTTP Consumer — the collection.
  • Maxlona Production — the environment template, with empty values.
What it runs
  • 01 — read and evaluate an existing flag. Changes nothing.
  • 02 — create, configure, toggle, evaluate, delete a temporary flag.
  • 03 — security checks that are meant to fail.
  • 04 — the same API over GraphQL.

Connect it to your account

  1. Unzip, then in Postman choose File → Import and import both JSON files.
  2. Pick Maxlona Production in the environment dropdown, top right.
  3. Create your keys under Management Keys: one with CanEvaluate scoped to an application for productionKey, and one with CanRead and CanWrite for managementKey. Each key is shown once, so copy it straight away.
  4. Paste them into the Current Value column, not Initial Value — current values stay on your machine and never travel with an export or a shared workspace.
  5. Fill in application, environment, flagName and userId with your own values. Leave runFlagName empty; the collection sets it while it runs.
  6. Run folder 01 first to confirm the keys work, then 02 top to bottom.
Keep the keys out of version control. The template ships empty on purpose. Once you have pasted a key in, treat the environment as a secret: don't export it, commit it, or share the workspace it lives in.

Prefer GraphQL? The Maxlona GraphQL Consumer collection ↓ covers the same API from a single endpoint — see the GraphQL page.

Authentication

Every integration request to /api/flags* or /flags/* must include an x-management-key header. The key carries its own org and permission scope.

x-management-key: YOUR-MANAGEMENT-KEY
Explicit permissions. CanEvaluate permits evaluation, CanRead permits Management API GETs, and CanWrite permits management POST/PUT/DELETE and automatically includes read. Missing permissions return 403.
Scope. CanEvaluate requires an application-scoped key. An optional environment scope restricts evaluation and config writes to that stage. Application scope filters all Management API flag access. Flag metadata endpoints do not take a stage, so environment scope is applied when evaluating or writing a stage configuration.

Key lifecycle

A key is 64 lowercase hex characters. The plaintext is returned once — in the create response and again on rotate — and is never retrievable afterwards, so store it in your secret manager immediately. The list view shows only the first 8 characters so you can tell keys apart. Only admin and globaladmin can create, rotate, disable, or delete keys.

Changes take up to 60 seconds to propagate. Authenticated keys are cached server-side for 60s, so a key you disable or rotate can keep authenticating until that entry expires. Treat rotation as deploy the new key first, then rotate, and don't expect a disable to cut off traffic instantly. Deleting a key behaves the same way.

Endpoints

MethodPathPurposePermission
Flags
GET/api/flagsList visible flag definitionsCanRead
GET/api/flags/:nameRead one flag definitionCanRead
POST/api/flagsCreate a flagCanWrite
PUT/api/flags/:namePartially update metadata or archive stateCanWrite
POST/api/flags/:name/archiveArchive a flagCanWrite
POST/api/flags/:name/restoreRestore an archived flagCanWrite
DELETE/api/flags/:nameDelete the flag and all configsCanWrite
Per-environment configuration
GET/api/flags/:name/configsList stage configs, optionally filtered by stageCanRead
POST/api/flags/:name/configsUpsert a stage configCanWrite
PATCH/api/flags/:name/configs/:stage/enabledTurn one stage on or off without resending the configCanWrite
DELETE/api/flags/:name/configs/:stageRemove one stage's configurationCanWrite
GET/api/flags/:name/environmentsList the environments the flag usesCanRead
PUT/api/flags/:name/environmentsReplace the flag's environment listCanWrite
Organization settings
GET/api/environmentsList the org's environmentsCanRead
PUT/api/environmentsReplace the environment listCanWrite
PATCH/api/environments/:nameRename one environmentCanWrite
GET/api/applicationsList the org's applicationsCanRead
PUT/api/applicationsReplace the application listCanWrite
PATCH/api/applications/:nameRename one applicationCanWrite
GET/api/kill-switchRead the current kill-switch stateCanRead
PUT/api/kill-switchReplace the kill-switch stateCanWrite
Evaluation
POST/flags/:nameEvaluate a flag for a userCanEvaluate
POST

/api/flags

Creates a new flag in the org owning the key. Returns 409 if a flag with the same name already exists.

Request headers

x-management-key: <your-key>
Content-Type: application/json

Request body fields

FieldTypeRequiredNotes
namestringyesUnique within the org.
projectstringyesMust match the key's application scope when one is set.
typestringnorelease, experiment, or ops. Default release.
ownerstringnoFree-text. Default api.
descriptionstringnoPlain text.
tagsstring[]noSearchable in the SPA.
variantsVariant[]noDefault is on/off booleans.
dependsOnstring[]noOther flag names this flag is gated by.

Request body (JSON — paste this into Postman)

{
  "name": "checkout-redesign",
  "project": "Main App",
  "type": "release",
  "description": "Q3 checkout flow rewrite",
  "tags": ["checkout", "q3"],
  "variants": [
    { "key": "on",  "value": true,  "valueType": "boolean" },
    { "key": "off", "value": false, "valueType": "boolean" }
  ],
  "dependsOn": []
}

Curl

curl -X POST $HOST/api/flags \
  -H "x-management-key: $FF_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  --data @create-flag.json

Response (201 Created)

{
  "name": "checkout-redesign",
  "type": "release",
  "project": "Main App",
  "owner": "api",
  "description": "Q3 checkout flow rewrite",
  "tags": ["checkout", "q3"],
  "variants": [{ "key": "on", "value": true, "valueType": "boolean" }, { "key": "off", "value": false, "valueType": "boolean" }],
  "dependsOn": [],
  "isArchived": false,
  "activatesAt": null,
  "expiresAt": null,
  "createdAt": "2026-05-17T18:30:00Z"
}
GET

/api/flags

Returns flag definitions newest first. An application-scoped key only receives flags in that application.

Curl

curl $HOST/api/flags \
  -H "x-management-key: $FF_MANAGEMENT_KEY"
GET

/api/flags/:name

Returns one flag definition or 404. It does not embed per-stage configs. An out-of-scope flag returns 403.

PUT

/api/flags/:name

Partial update — every body field is optional, only the fields you send are changed. Variants, archive state, tags, dependencies, owner, project, description are all updatable here. Per-stage toggle/rollout/rules are on the configs endpoint below.

Request body (edit description + tags)

{
  "description": "Approved by Eng leadership",
  "tags": ["checkout", "q3", "approved"]
}

Archive a flag (one-field body)

{ "isArchived": true }

Curl

curl -X PUT $HOST/api/flags/checkout-redesign \
  -H "x-management-key: $FF_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  --data @update-flag.json
DELETE

/api/flags/:name

Permanently removes the flag and every per-stage config row that references it in one transaction. Cache is purged immediately. Subsequent eval requests for this flag return 404.

Curl

curl -X DELETE $HOST/api/flags/checkout-redesign \
  -H "x-management-key: $FF_MANAGEMENT_KEY"
POST

/api/flags/:name/configs

Creates or updates the per-stage configuration for one (flag, stage) pair. This is what you call to enable / disable a flag in a specific environment, set its rollout percentage, or install targeting rules. Only the cache entry for that exact (flag, stage) is invalidated — other envs keep their warm cache.

If a running automation plan still controls that environment, writing its configuration here — or through the enabled and DELETE config endpoints — suspends the plan in the same save, so its next step can't overwrite your change. The plan's reason says a Management API key made the change; resume it from the flag's Automation tab.

Request body fields

FieldTypeRequiredNotes
stagestringyesdev, uat, production, etc. Stored as sent and matched exactly at evaluation time, so a stage that doesn't match what your SDK evaluates with creates a config nothing ever reads. Must equal the key's environment scope when one is set. Creating a config returns 409 if the flag doesn't use that environment (it was removed from the flag, or is opt-in and not added); updating an existing config is always allowed.
enabledbooleannoMaster switch; omitted JSON binds to false.
clientIdstring?noOptional client-scoped override. Most callers leave null.
defaultVariantKeystringnoReturned when no rule matches. Defaults to "off".
rolloutPercentagenumberno0–100. Users outside the window get off. Defaults to 100.
rulesRule[]noEvaluated highest priority first; the first rule whose conditions all match wins. Each condition's field is looked up as a top-level key of the evaluation context — matched exactly, with no attributes. prefix. Defaults to empty.
enrollmentEndsAtISO 8601?noOptional cutoff for new experiment enrollment.

Enable at 25% in production

{
  "stage": "production",
  "enabled": true,
  "defaultVariantKey": "off",
  "rolloutPercentage": 25,
  "rules": []
}

Targeted rule — Pro users only

{
  "stage": "production",
  "enabled": true,
  "defaultVariantKey": "off",
  "rolloutPercentage": 100,
  "rules": [
    {
      "id": "pro-users",
      "priority": 10,
      "conditions": [
        { "field": "plan", "operator": "==", "value": "pro" }
      ],
      "allocations": [
        { "variantKey": "on", "percentage": 100 }
      ]
    }
  ]
}

Curl

curl -X POST $HOST/api/flags/checkout-redesign/configs \
  -H "x-management-key: $FF_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  --data @config.json

Response (200 OK)

{
  "id": "0d5b9b04-9b6e-4d1d-bc11-a3a73e6e0001",
  "flagId": "checkout-redesign",
  "stage": "production",
  "clientId": null,
  "enabled": true,
  "defaultVariantKey": "off",
  "rolloutPercentage": 25,
  "rules": []
}

Querying flag values (Evaluation API)

The hot read path is served by the Management API on the same host as the rest of the platform, under POST /flags/{key}. It uses its own per-key rate-limit policy so evaluation traffic stays isolated from flag reads and writes. It authenticates through the same x-management-key header used by the rest of this page. Create the key under Management Keys with CanEvaluate permission and an application scope; environment scope is optional.

Two things reject an evaluation before any flag is read:

  • An org-wide key (no application scope) always returns 403 — “Evaluation requires a management key scoped to one application.” Read and write keys may be org-wide; evaluation keys may not.
  • An environment-scoped key whose scope doesn't equal the request's stage returns 403 — “Invalid management key for this environment.” The comparison is case-insensitive, and the key's spelling of the stage is what config lookup then uses, so "Production" in the body resolves against a key scoped to production. One key per environment means one key per stage you test.
FieldRequiredNotes
userIdyesStable identifier used by targeting and rollout bucketing.
stageyesMust match the key's environment scope when set.
clientIdnoOptional client configuration selector.
contextnoFree-form targeting values.
explainnoBoolean query parameter; adds the reason object.
Evaluation requests are in the same Maxlona HTTP Consumer collection as the Management API (see the download above) — folder 01 evaluates an existing flag on its own, and folder 02 walks a flag from create through targeted and default evaluation to delete.

Curl

curl -X POST "$HOST/flags/checkout-redesign?explain=true" \
  -H "x-management-key: $FF_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-42",
    "stage": "production",
    "context": { "plan": "pro", "country": "DE" }
  }'

Response

{
  "variant": true,
  "key": "on",
  "reason": {
    "code": "rule_matched",
    "message": "Matched rule 'pro-users' (priority 10). Variant chosen by allocation.",
    "ruleId": "pro-users"
  }
}

Calling it from your language

The same requests documented above, written with each language's own HTTP client — no dependency to add. Swap in your host, Management Key, flag name, and stage. If you are on .NET, prefer the official SDK package over hand-rolled HTTP.

Setup

// No install needed — Node 18+ ships a built-in fetch

Request code

const BASE_URL = 'https://maxlona.com';
const MANAGEMENT_KEY = 'YOUR_MANAGEMENT_KEY';
const STAGE = 'production';

async function evaluateFlag(flagKey, userId, context = {}) {
  const response = await fetch(BASE_URL + '/flags/' + flagKey, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-management-key': MANAGEMENT_KEY
    },
    body: JSON.stringify({
      userId, stage: STAGE, clientId: '', context
    })
  });

  if (!response.ok) throw new Error('Evaluation failed: ' + response.status);
  return await response.json(); // { key: "control", variant: ... }
}

function isEnabled(result) {
  return result.key !== 'off' && result.key !== '';
}

// Usage
async function main() {
  const context = { lenderId: '100' };

  const result = await evaluateFlag('my-feature-flag', 'user-123', context);
  console.log('Enabled:', isEnabled(result));
  console.log('Key:', result.key);         // "control", "treatment", etc.
  console.log('Variant:', result.variant); // true, "classic", 42, "#3b82f6"
}

main().catch(console.error);

Error responses

StatusWhen
400Required data is missing or the request body is malformed.
401x-management-key is missing, unknown, or disabled.
402The organization does not have an active subscription.
403The key lacks the permission the endpoint requires, or the request violates the key's scope: evaluating with an org-wide key, evaluating or writing a config for a stage outside the key's environment scope, or touching a flag outside its application scope. The response message names which.
404Flag or evaluation configuration not found.
409Tried to create a flag whose name already exists in the org, or a stage config in an environment the flag doesn't use. Add the environment on the flag's Manage environments dialog first. Also returned when a flag is created or updated with a dependency on a parent that is missing one of the flag's environments; add that environment to the parent first.
429Rate limit exceeded.
500Unexpected server-side error.

Prefer a typed client to raw HTTP? The official Maxlona.FeatureFlags.Offline NuGet package wraps every endpoint on this page — offline evaluation from an encrypted local cache kept current over a realtime SignalR connection, evaluation with typed variants, and the full Management API — for .NET 8 and later.