{
  "openapi": "3.1.0",
  "info": {
    "title": "Brand Engine API",
    "version": "1.0.0",
    "description": "Public HTTP API for the Brand Engine hub: brand identity bundles, federation tokens, events, and webhook subscriptions. Human-readable docs: https://thebrandengine.ai/developers/reference"
  },
  "servers": [
    {
      "url": "https://thebrandengine.ai"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Brand-scoped API key issued from the hub (be_…)."
      },
      "federationToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "User session token or short-lived federation JWT."
      },
      "childToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "CORE_CHILD_APP_TOKEN__<TOOL>, paired with the X-Tool-Slug header."
      },
      "dispatchSecret": {
        "type": "http",
        "scheme": "bearer",
        "description": "Hub-internal WEBHOOK_DISPATCH_SECRET."
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "bad_request",
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "rate_limited",
                  "server_error"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        },
        "example": {
          "error": {
            "code": "unauthorized",
            "message": "Missing or invalid API key"
          }
        }
      }
    }
  },
  "paths": {
    "/api/public/tools": {
      "get": {
        "operationId": "tools-list",
        "summary": "List tools available in the ecosystem, with this brand's entitlement state.",
        "description": "Returns every tool registered on the hub plus whether the calling brand is entitled to it. Use it to render a tool launcher inside a child app.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <api key>. Brand-scoped.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "tools": [
                    {
                      "slug": "dialog-center",
                      "name": "Dialog Center",
                      "status": "active",
                      "entitled": true
                    }
                  ]
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/brands": {
      "get": {
        "operationId": "brands-list",
        "summary": "List brands the API key can access. For brand-scoped keys this returns the one brand.",
        "description": "Also accepts a signed-in user session token (JWT), in which case it returns every brand the user is a member of together with their role.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <api key> or Bearer <user JWT>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "brands": [
                    {
                      "id": "8f1c...",
                      "slug": "acme",
                      "name": "Acme",
                      "identity_version": 12,
                      "role": "api-key"
                    }
                  ]
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/brands/me": {
      "get": {
        "operationId": "brands-me",
        "summary": "List every brand the signed-in user is a member of. Used by children to render a brand switcher.",
        "description": "List every brand the signed-in user is a member of. Used by children to render a brand switcher.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "federationToken": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <user session token>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "brands": [
                    {
                      "id": "8f1c...",
                      "slug": "acme",
                      "name": "Acme",
                      "identity_version": 12,
                      "role": "owner"
                    }
                  ],
                  "active_brand_id": "8f1c..."
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/brand/me": {
      "get": {
        "operationId": "brand-me",
        "summary": "Active brand identity. Honors X-Brand-Id when the caller is a member of the requested brand.",
        "description": "Returns the compiled brand identity for the caller's active brand. The response carries both brand_identity (current) and brand_book (deprecated alias) so older children keep working.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "federationToken": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <user session token>.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Brand-Id",
            "in": "header",
            "required": false,
            "description": "Target a specific brand the user is a member of. Defaults to the active brand.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "brand": {
                    "id": "8f1c...",
                    "slug": "acme",
                    "name": "Acme"
                  },
                  "brand_identity": {
                    "...": "compiled identity"
                  },
                  "brand_identity_version": 12
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Caller is not a member of the requested brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/events": {
      "post": {
        "operationId": "events-v0",
        "summary": "Emit an orchestration event other tools can react to.",
        "description": "Loose v0 ingestion kept for backwards compatibility. New integrations should use POST /api/public/v1/events, which is schema-locked and idempotent.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <api key>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "type": "campaign.sent",
                "payload": {
                  "campaign_id": "c_123"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Body failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/federation/mint": {
      "post": {
        "operationId": "federation-mint",
        "summary": "Mint a short-lived federation token. Optional { brand_id } body to target a specific brand.",
        "description": "Called from the hub session (or with a user session token). The returned HS256 JWT lives ~5 minutes and is what a child presents to /federation/exchange.",
        "tags": [
          "v0 public API"
        ],
        "security": [
          {
            "federationToken": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <user session token>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "brand_id": "8f1c..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "token": "eyJhbGciOiJIUzI1NiJ9...",
                  "expires_at": 1767200000
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/federation/exchange": {
      "post": {
        "operationId": "federation-exchange",
        "summary": "Exchange a federation token for the user's brand context.",
        "description": "Public because the token itself is the credential. Verify the returned brand id against your own cache key before serving data.",
        "tags": [
          "v0 public API"
        ],
        "security": [],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "token": "eyJhbGciOiJIUzI1NiJ9..."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token valid.",
            "content": {
              "application/json": {
                "example": {
                  "user_id": "u_123",
                  "brand_id": "8f1c...",
                  "role": "owner",
                  "entitlements": [
                    "dialog-center"
                  ]
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Token expired, malformed, or badly signed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/brand/by-id/{id}/bundle": {
      "get": {
        "operationId": "brand-bundle",
        "summary": "Server-to-server brand bundle. Pass ?since=<version> for 304-style not_modified.",
        "description": "The canonical read for children. Call it from your backend only — never from the browser. Cache the result in a brand_cache table keyed by brand_id and store identity_version alongside it.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [
          {
            "childToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Brand id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "The identity_version you already have cached. When it matches, the hub returns { not_modified: true } instead of the full bundle.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <CORE_CHILD_APP_TOKEN__TOOL>.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Tool-Slug",
            "in": "header",
            "required": true,
            "description": "The child tool slug the token belongs to, e.g. dialog-center.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bundle returned (or { not_modified: true }).",
            "content": {
              "application/json": {
                "example": {
                  "brand": {
                    "id": "8f1c...",
                    "slug": "acme",
                    "name": "Acme"
                  },
                  "identity_version": 12,
                  "identity": {
                    "...": "brand data + personality + persona"
                  },
                  "colors": {
                    "source": "mixed",
                    "palette": [
                      {
                        "id": "col_ab12cd34",
                        "name": "Signal Sapphire",
                        "role": "primary",
                        "hex": "#1b3a8f",
                        "rgb": {
                          "r": 27,
                          "g": 58,
                          "b": 143
                        },
                        "usage": "Primary buttons, links, brand marks",
                        "locked": true
                      }
                    ]
                  },
                  "logos": {
                    "items": [
                      {
                        "id": "logo_9f8e7d6c",
                        "variant": "logo_positive",
                        "label": "Logo — positive",
                        "usage": "Default lockup on light backgrounds",
                        "background": "light",
                        "clear_space": "1x cap height",
                        "min_width_px": 120,
                        "asset_id": "3d2c...",
                        "url": "https://...signed",
                        "mime": "image/png"
                      }
                    ],
                    "rules": [
                      "Never recolour the mark",
                      "Never place the positive logo on dark backgrounds"
                    ]
                  },
                  "assets": [
                    {
                      "kind": "logo",
                      "url": "https://...signed"
                    }
                  ]
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Bad child token or tool slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Brand is not entitled to this tool.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Brand not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/events": {
      "post": {
        "operationId": "events-v1",
        "summary": "Locked schema, idempotent event ingestion.",
        "description": "Send an idempotency_key with every event. Re-sending the same key is a no-op, so retries after a network blip never duplicate.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [
          {
            "childToken": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <CORE_CHILD_APP_TOKEN__TOOL>.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Tool-Slug",
            "in": "header",
            "required": true,
            "description": "Child tool slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "brand_id": "8f1c...",
                "type": "message.delivered",
                "occurred_at": "2026-07-29T10:00:00.000Z",
                "idempotency_key": "msg_9931:delivered",
                "trace_id": "t_abc",
                "payload": {
                  "message_id": "msg_9931"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted (or deduplicated).",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "deduped": false
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Body failed schema validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Bad child token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Brand is not entitled to this tool.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/internal/dispatch-tick": {
      "post": {
        "operationId": "dispatch-tick",
        "summary": "Cron-driven webhook fan-out tick.",
        "description": "Hub-internal. Driven by a scheduled job every minute; drains pending child_context_deliveries with exponential backoff. Documented for completeness — child projects never call it.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [
          {
            "dispatchSecret": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <WEBHOOK_DISPATCH_SECRET>. Hub-only secret.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "processed": 4,
                  "failed": 0
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/internal/register-subscription": {
      "post": {
        "operationId": "register-subscription",
        "summary": "Admin upsert of (brand_id, tool_slug) → webhook_url.",
        "description": "Hub-internal. Normally handled automatically by the entitlement trigger using the tool's default webhook URL.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [
          {
            "dispatchSecret": []
          }
        ],
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "description": "Bearer <WEBHOOK_DISPATCH_SECRET>.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "brand_id": "8f1c...",
                "tool_slug": "dialog-center",
                "webhook_url": "https://dialog.example.com/api/public/webhooks/identity"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected hub error. Safe to retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/docs/openapi.json": {
      "get": {
        "operationId": "docs-openapi",
        "summary": "Machine-readable OpenAPI 3.1 description of this API.",
        "description": "Generated from the same source as this page. Point your codegen, agent, or API client at it instead of scraping the docs.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OpenAPI document.",
            "content": {
              "application/json": {
                "example": {
                  "openapi": "3.1.0",
                  "info": {
                    "title": "Brand Engine API"
                  }
                },
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/docs/api.pdf": {
      "get": {
        "operationId": "docs-pdf",
        "summary": "Download the current API documentation as a PDF.",
        "description": "Secondary export. The HTML reference at /developers/reference is the primary, always-current format.",
        "tags": [
          "v1 ecosystem contract"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "PDF document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  }
}