{
  "openapi": "3.1.0",
  "info": {
    "title": "LaunchFlag API",
    "version": "1.0.0",
    "summary": "Feature flags and kill switches, evaluated in your own process.",
    "description": "Two families. The evaluation endpoints take an environment key (lf_dev_, lf_staging_, lf_prod_) and answer what a flag is for a user; the SDK calls these for you and caches the config, so most apps never call them directly. The management endpoints under /api/v1 take an API token (lfk_) and create, change, promote and delete flags. The same management surface is available to agents over MCP at /api/mcp.",
    "contact": {
      "name": "LaunchFlag",
      "url": "https://launchflag.dev",
      "email": "contact@launchflag.dev"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://launchflag.dev/terms"
    }
  },
  "servers": [
    {
      "url": "https://launchflag.dev"
    }
  ],
  "externalDocs": {
    "description": "Full documentation",
    "url": "https://launchflag.dev/docs"
  },
  "tags": [
    {
      "name": "Evaluation",
      "description": "Answer what a flag is, for a user, in one environment."
    },
    {
      "name": "Management",
      "description": "Create, change, promote and delete flags."
    },
    {
      "name": "Meta",
      "description": "Health and status."
    }
  ],
  "components": {
    "securitySchemes": {
      "environmentKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An environment key: lf_dev_, lf_staging_ or lf_prod_. Scoped to one environment, read only, 600 requests a minute. The publishable key (lfpub_) is the browser-safe variant."
      },
      "apiToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "An lfk_ API token from the dashboard, 120 requests a minute. Its scope caps what it may do: full is everything you can do, CI changes flags in dev and staging only, read only changes nothing."
      }
    },
    "schemas": {
      "Evaluation": {
        "type": "object",
        "required": [
          "enabled",
          "variant"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "variant": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": "string",
            "description": "Why the answer is what it is, such as \"disabled\"."
          }
        }
      },
      "Flag": {
        "type": "object",
        "required": [
          "key"
        ],
        "properties": {
          "key": {
            "type": "string",
            "examples": [
              "checkout_v2"
            ]
          },
          "description": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "boolean",
              "multivariate"
            ]
          },
          "failMode": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ],
            "description": "What your app should answer when it cannot reach us. Closed for money and auth."
          },
          "essential": {
            "type": "boolean",
            "description": "Essential flags are left alone by emergency off."
          },
          "requires": {
            "type": [
              "string",
              "null"
            ],
            "description": "Key of a flag this one depends on. While that flag is off for a user, this one is off for them too. Cycles are refused.",
            "examples": [
              "new_pricing"
            ]
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    },
    "responses": {
      "Error": {
        "description": "A JSON error with a message that says how to fix it",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "Missing API token. Send Authorization: Bearer lfk_…"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/eval": {
      "get": {
        "tags": [
          "Evaluation"
        ],
        "operationId": "evaluateFlag",
        "summary": "Evaluate one flag for one user",
        "security": [
          {
            "environmentKey": []
          }
        ],
        "parameters": [
          {
            "name": "flag",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer for this user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Evaluation"
                },
                "example": {
                  "enabled": false,
                  "reason": "disabled",
                  "variant": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/flags": {
      "get": {
        "tags": [
          "Evaluation"
        ],
        "operationId": "evaluateAll",
        "summary": "Every flag in this environment, evaluated for one user",
        "description": "Always returns the whole environment. `keys` registers keys we have not seen, it never filters.",
        "security": [
          {
            "environmentKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "keys",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Every flag, evaluated"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/config": {
      "get": {
        "tags": [
          "Evaluation"
        ],
        "operationId": "getConfig",
        "summary": "The rule set for one environment",
        "description": "What the SDK polls to evaluate locally. Contains rules, never user data. ETag is the version.",
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The environment's rule set"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/flags": {
      "get": {
        "tags": [
          "Management"
        ],
        "operationId": "listFlags",
        "summary": "List flags",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The project's flags"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "tags": [
          "Management"
        ],
        "operationId": "createFlag",
        "summary": "Create a flag, off in every environment",
        "security": [
          {
            "apiToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Flag"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created flag"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/flags/{key}": {
      "parameters": [
        {
          "name": "key",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "patch": {
        "tags": [
          "Management"
        ],
        "operationId": "updateFlag",
        "summary": "Turn a flag on or off, or change its targeting",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "The updated flag"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "tags": [
          "Management"
        ],
        "operationId": "deleteFlag",
        "summary": "Delete a flag",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/flags/{key}/promote": {
      "parameters": [
        {
          "name": "key",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "tags": [
          "Management"
        ],
        "operationId": "promoteFlag",
        "summary": "Promote a flag's state to the next environment",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Promoted"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/flags/cleanup": {
      "get": {
        "tags": [
          "Management"
        ],
        "operationId": "cleanupFlags",
        "summary": "Flags whose rollout is over and whose code can be deleted",
        "description": "Settled flags are on for everyone in every environment and unchanged long enough that the rollout is clearly finished. Each carries the reason and the edit to make.",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Settled and stale flags, with the edit for each"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/emergency": {
      "post": {
        "tags": [
          "Management"
        ],
        "operationId": "emergencyOff",
        "summary": "Turn every non-essential flag off, in every environment",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Emergency off applied"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/v1/projects": {
      "get": {
        "tags": [
          "Management"
        ],
        "operationId": "listProjects",
        "summary": "Projects this token can reach",
        "security": [
          {
            "apiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Projects"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/status": {
      "get": {
        "tags": [
          "Meta"
        ],
        "operationId": "getStatus",
        "summary": "Live health checks, run at request time",
        "description": "Never a cached answer. Also rendered for people at /status.",
        "responses": {
          "200": {
            "description": "Database, flag delivery and evaluation engine, each with timing"
          }
        }
      }
    }
  }
}