{
  "openapi": "3.1.0",
  "info": {
    "title": "Fleece AI API",
    "version": "1.0.0",
    "description": "The Fleece AI REST API lets you manage agents, trigger flows, and retrieve execution results programmatically. API access requires a **Pro plan or higher**.\n\nAll requests must include a valid API key in the `Authorization` header:\n```\nAuthorization: Bearer flc_your_key_here\n```\n\nAPI keys can be created from **Settings > API Keys** in the Fleece AI dashboard.",
    "contact": {
      "name": "Fleece AI Support",
      "url": "https://fleeceai.app/contact",
      "email": "contact@fleeceai.app"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://fleeceai.app/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Agents",
      "description": "Create, list, and execute AI agents"
    },
    {
      "name": "Flows",
      "description": "Manage automated workflows and their execution history"
    },
    {
      "name": "API Keys",
      "description": "Create and manage API keys for authentication"
    }
  ],
  "paths": {
    "/agents": {
      "get": {
        "operationId": "listAgents",
        "tags": ["Agents"],
        "summary": "List agents",
        "description": "Returns all agents belonging to the authenticated user.",
        "responses": {
          "200": {
            "description": "List of agents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Agent" }
                    },
                    "total": { "type": "integer" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/PlanRequired" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/agents/{agentId}": {
      "get": {
        "operationId": "getAgent",
        "tags": ["Agents"],
        "summary": "Get agent details",
        "description": "Returns full details for a single agent, including capabilities, model configuration, and metrics.",
        "parameters": [
          {
            "name": "agentId",
            "in": "path",
            "required": true,
            "description": "UUID of the agent",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Agent details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Agent" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/agents/{agentId}/execute": {
      "post": {
        "operationId": "executeAgent",
        "tags": ["Agents"],
        "summary": "Execute an agent",
        "description": "Send a message to an agent and receive its response. The agent will use its configured tools and integrations to complete the task. Consumes credits based on the model used (1 credit for GPT-5.2, 10 for Claude Opus 4.7).",
        "parameters": [
          {
            "name": "agentId",
            "in": "path",
            "required": true,
            "description": "UUID of the agent to execute",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExecuteAgentRequest"
              },
              "example": {
                "task": "Summarize my last 5 emails and flag anything urgent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent execution result",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/AgentExecutionResult" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/PlanRequired" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/flows": {
      "get": {
        "operationId": "listFlows",
        "tags": ["Flows"],
        "summary": "List flows",
        "description": "Returns all flows belonging to the authenticated user.",
        "responses": {
          "200": {
            "description": "List of flows",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Flow" }
                    },
                    "total": { "type": "integer" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/PlanRequired" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/flows/{flowId}": {
      "get": {
        "operationId": "getFlow",
        "tags": ["Flows"],
        "summary": "Get flow details",
        "description": "Returns full details for a single flow, including schedule, integrations, and run statistics.",
        "parameters": [
          {
            "name": "flowId",
            "in": "path",
            "required": true,
            "description": "UUID of the flow",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Flow details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Flow" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/flows/{flowId}/trigger": {
      "post": {
        "operationId": "triggerFlow",
        "tags": ["Flows"],
        "summary": "Trigger a flow",
        "description": "Manually trigger a flow execution outside its cron schedule. Creates a new flow run and starts execution immediately. The flow must be in `active` status.",
        "parameters": [
          {
            "name": "flowId",
            "in": "path",
            "required": true,
            "description": "UUID of the flow to trigger",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Flow run created",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FlowRun" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/PlanRequired" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": {
            "description": "Flow is already running",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/flows/{flowId}/runs": {
      "get": {
        "operationId": "listFlowRuns",
        "tags": ["Flows"],
        "summary": "List flow runs",
        "description": "Returns the execution history for a specific flow, ordered by most recent first.",
        "parameters": [
          {
            "name": "flowId",
            "in": "path",
            "required": true,
            "description": "UUID of the flow",
            "schema": { "type": "string", "format": "uuid" }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of runs to return (default 50, max 100)",
            "required": false,
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }
          }
        ],
        "responses": {
          "200": {
            "description": "List of flow runs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/FlowRun" }
                    },
                    "total": { "type": "integer" },
                    "flowId": { "type": "string", "format": "uuid" }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/flows/{flowId}/runs/{runId}": {
      "get": {
        "operationId": "getFlowRun",
        "tags": ["Flows"],
        "summary": "Get flow run details",
        "description": "Returns full details for a single flow run, including tool calls, result data, and error messages.",
        "parameters": [
          {
            "name": "flowId",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          },
          {
            "name": "runId",
            "in": "path",
            "required": true,
            "description": "UUID of the flow run",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Flow run details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FlowRun" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/keys": {
      "get": {
        "operationId": "listApiKeys",
        "tags": ["API Keys"],
        "summary": "List API keys",
        "description": "Returns all API keys for the authenticated user. Only the key prefix is returned — full keys are never retrievable after creation.",
        "responses": {
          "200": {
            "description": "List of API keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKeyInfo"
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "tags": ["API Keys"],
        "summary": "Create an API key",
        "description": "Generates a new API key. The full plaintext key is returned **only in this response** — store it securely. Subsequent requests only show the prefix.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 100,
                    "description": "A label to identify this key (e.g. \"Production\", \"CI/CD\")",
                    "example": "My Production Key"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key created — the `key` field contains the full plaintext key (shown once)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiKeyCreated" }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing or invalid name)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/PlanRequired" }
        }
      }
    },
    "/keys/{keyId}": {
      "delete": {
        "operationId": "deleteApiKey",
        "tags": ["API Keys"],
        "summary": "Delete an API key",
        "description": "Permanently revokes an API key. Any application using this key will immediately lose access.",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "description": "UUID of the API key to delete",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Key deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "example": true }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key generated from the Fleece AI dashboard (Settings > API Keys). Format: `flc_` followed by 48 hexadecimal characters."
      }
    },
    "schemas": {
      "Agent": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string", "example": "Email Triager" },
          "description": { "type": "string", "example": "Categorizes and summarizes incoming emails" },
          "type": {
            "type": "string",
            "enum": ["general", "email", "calendar", "documents", "data", "social", "custom"]
          },
          "icon": { "type": "string", "description": "Emoji or icon identifier", "example": "📧" },
          "model": { "type": "string", "example": "gpt-5.2" },
          "provider": { "type": "string", "example": "openai" },
          "capabilities": {
            "type": "array",
            "items": { "type": "string" },
            "description": "List of skill identifiers assigned to this agent",
            "example": ["email-assistant", "summarizer"]
          },
          "isActive": { "type": "boolean" },
          "totalTasksCompleted": { "type": "integer", "example": 142 },
          "totalTasksFailed": { "type": "integer", "example": 3 },
          "averageExecutionTime": { "type": "integer", "description": "Average execution time in seconds", "example": 12 },
          "lastActiveAt": { "type": "string", "format": "date-time" },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      },
      "ExecuteAgentRequest": {
        "type": "object",
        "required": ["task"],
        "properties": {
          "task": {
            "type": "string",
            "description": "The instruction or task to send to the agent",
            "example": "Summarize my last 5 emails and flag anything urgent"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone for time-aware tasks",
            "example": "Europe/Paris"
          }
        }
      },
      "AgentExecutionResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid", "description": "Execution ID" },
          "agentId": { "type": "string", "format": "uuid" },
          "status": { "type": "string", "enum": ["completed", "failed"] },
          "result": { "type": "string", "description": "The agent's response text" },
          "toolCalls": {
            "type": "array",
            "description": "Tools invoked during execution",
            "items": {
              "$ref": "#/components/schemas/ToolCall"
            }
          },
          "tokensUsed": { "type": "integer", "example": 1523 },
          "durationMs": { "type": "integer", "description": "Execution duration in milliseconds", "example": 4200 },
          "error": { "type": "string", "description": "Error message if status is `failed`" }
        }
      },
      "Flow": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string", "example": "Weekly Gmail Summary to Slack" },
          "description": { "type": "string", "example": "Every Monday at 9 AM, summarize unread emails and post to #general" },
          "icon": { "type": "string", "example": "📊" },
          "cronExpression": { "type": "string", "example": "0 9 * * 1" },
          "scheduleDescription": { "type": "string", "example": "Every Monday at 9:00 AM" },
          "timezone": { "type": "string", "example": "Europe/Paris" },
          "mode": {
            "type": "string",
            "enum": ["auto", "always_ask"],
            "description": "`auto` runs without intervention, `always_ask` requires approval before each execution"
          },
          "status": {
            "type": "string",
            "enum": ["active", "paused", "error", "draft"]
          },
          "model": { "type": "string", "example": "gpt-5.2" },
          "integrations": {
            "type": "array",
            "description": "Connected services used by this flow",
            "items": {
              "type": "object",
              "properties": {
                "serviceId": { "type": "string", "example": "gmail" },
                "serviceName": { "type": "string", "example": "Gmail" },
                "connected": { "type": "boolean" }
              }
            }
          },
          "isRunning": { "type": "boolean", "description": "Whether the flow is currently executing" },
          "estimatedHumanMinutes": {
            "type": "integer",
            "description": "Estimated time a human would take (minutes) — used for Time Saved metrics",
            "example": 15
          },
          "lastRunAt": { "type": "string", "format": "date-time" },
          "nextRunAt": { "type": "string", "format": "date-time" },
          "totalRuns": { "type": "integer", "example": 87 },
          "totalFailures": { "type": "integer", "example": 2 },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      },
      "FlowRun": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "flowId": { "type": "string", "format": "uuid" },
          "status": {
            "type": "string",
            "enum": ["pending", "approved", "running", "completed", "failed", "skipped"]
          },
          "startedAt": { "type": "string", "format": "date-time" },
          "completedAt": { "type": "string", "format": "date-time" },
          "durationMs": { "type": "integer", "description": "Execution time in milliseconds", "example": 8340 },
          "resultSummary": { "type": "string", "description": "Human-readable summary of the run outcome" },
          "resultData": { "type": "object", "description": "Structured result data (varies by flow)" },
          "toolCalls": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ToolCall" }
          },
          "tokensUsed": { "type": "integer" },
          "errorMessage": { "type": "string", "description": "Error details if status is `failed`" },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "ToolCall": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "description": "Tool/integration name", "example": "gmail-send-email" },
          "arguments": { "type": "object", "description": "Arguments passed to the tool" },
          "result": { "type": "object", "description": "Tool execution result" }
        }
      },
      "ApiKeyInfo": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string", "example": "My Production Key" },
          "keyPrefix": { "type": "string", "description": "First 12 characters of the key", "example": "flc_a1b2c3d4" },
          "isActive": { "type": "boolean" },
          "lastUsedAt": { "type": "string", "format": "date-time", "nullable": true },
          "expiresAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "key": { "type": "string", "description": "Full plaintext API key — shown **only once**. Store it securely.", "example": "flc_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4" },
          "keyPrefix": { "type": "string", "example": "flc_a1b2c3d4" },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": { "type": "string", "description": "Human-readable error message" },
          "plan": { "type": "string", "description": "Current plan (included in limit errors)" },
          "upgrade": { "type": "boolean", "description": "If true, upgrading your plan would resolve this error" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "error": "Unauthorized" }
          }
        }
      },
      "PlanRequired": {
        "description": "Feature requires Pro plan or higher",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "error": "API access requires Pro plan or higher", "plan": "free", "upgrade": true }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "error": "Not found" }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying",
            "schema": { "type": "integer" }
          },
          "X-RateLimit-Limit": {
            "description": "Max requests per window",
            "schema": { "type": "integer" }
          },
          "X-RateLimit-Remaining": {
            "description": "Requests remaining in current window",
            "schema": { "type": "integer" }
          },
          "X-RateLimit-Reset": {
            "description": "Unix timestamp when the window resets",
            "schema": { "type": "integer" }
          }
        },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "error": "Rate limit exceeded" }
          }
        }
      }
    }
  }
}
