> ## Documentation Index
> Fetch the complete documentation index at: https://feather.mupeni.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluate Flags (Bulk)

> Evaluates up to 100 feature flags in one request.

Returns a `results` map keyed by flag key and a `meta` block with evaluation metadata.

**Auth**: API key only (`Authorization: Bearer <key>`).

## Body

<ParamField body="flags" type="string[]" required>
  List of flag keys to evaluate. Minimum 1, maximum 100.
</ParamField>

<ParamField body="context" type="object" required>
  Shared evaluation context for all requested flags.
</ParamField>

<ParamField body="context.userId" type="string">
  Stable user identifier.
</ParamField>

<ParamField body="context.anonymousId" type="string">
  Anonymous identifier when `userId` is not available.
</ParamField>

<ParamField body="context.attributes" type="Record<string, string | number | boolean>">
  Additional attributes used by flag rules.
</ParamField>

## Response

<ResponseField name="results" type="Record<string, { value: boolean | string | number | null; reason: &#x22;DISABLED&#x22; | &#x22;RULE_MATCH&#x22; | &#x22;ROLLOUT&#x22; | &#x22;DEFAULT&#x22; | &#x22;FLAG_NOT_FOUND&#x22; | &#x22;ERROR&#x22;; ruleId?: string; variant?: string }>" required />

<ResponseField name="meta.environmentId" type="string" required />

<ResponseField name="meta.evaluatedAt" type="string" required />

<ResponseField name="meta.cacheAge" type="number" required />

<ResponseField name="meta.requestId" type="string" />

<Info>Unknown flags and client-restricted flags both return `FLAG_NOT_FOUND`.</Info>

## Status codes

| Status | Meaning                                                     |
| ------ | ----------------------------------------------------------- |
| `200`  | Evaluation succeeded                                        |
| `400`  | Invalid JSON body (`INVALID_JSON`)                          |
| `401`  | Missing/invalid API key (`UNAUTHORIZED`, `INVALID_API_KEY`) |
| `422`  | Validation failed (`VALIDATION_ERROR`)                      |
| `429`  | Rate-limited (`RATE_LIMITED`)                               |
| `503`  | Bundle unavailable; all results return `reason: "ERROR"`    |

<RequestExample>
  ```bash theme={null}
  curl -X POST https://fly.feather.mupeni.dev/v1/evaluate/bulk \
    -H "Authorization: Bearer <api_key>" \
    -H "Content-Type: application/json" \
    -d '{
      "flags": ["new-checkout", "checkout-copy"],
      "context": {
        "userId": "user_123",
        "attributes": { "country": "DE" }
      }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "results": {
      "new-checkout": { "value": true, "reason": "DEFAULT" },
      "checkout-copy": { "value": "variant-b", "reason": "ROLLOUT", "variant": "b" }
    },
    "meta": {
      "environmentId": "env_01hx...",
      "evaluatedAt": "2026-04-03T10:00:00.000Z",
      "cacheAge": 2,
      "requestId": "73d24f43-d5ac-428e-b57a-fce4cb4d5685"
    }
  }
  ```

  ```json 503 theme={null}
  {
    "results": {
      "new-checkout": { "value": null, "reason": "ERROR" },
      "checkout-copy": { "value": null, "reason": "ERROR" }
    },
    "meta": {
      "environmentId": "env_01hx...",
      "evaluatedAt": "2026-04-03T10:00:00.000Z",
      "cacheAge": 0
    }
  }
  ```
</ResponseExample>
