{
  "openapi": "3.1.0",
  "info": {
    "title": "Loresta Agent API",
    "version": "1.0.0",
    "description": "Tenant-scoped creator relationship intelligence. Loresta classifies and drafts within creator-approved voice, facts, offers, and safety rules. It is not an unrestricted model proxy and never exposes social provider credentials."
  },
  "servers": [{ "url": "https://loresta.co" }],
  "security": [{ "LorestaAgentKey": [] }],
  "paths": {
    "/api/v1/agent/draft": {
      "post": {
        "operationId": "draftReply",
        "summary": "Classify an inbound message and draft a safe creator reply",
        "description": "Requires replies:write. This endpoint never sends a message. Idempotency prevents duplicate model charges during retries.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["profileId", "message"],
                "additionalProperties": false,
                "properties": {
                  "profileId": { "type": "string", "maxLength": 120 },
                  "message": { "type": "string", "minLength": 2, "maxLength": 800 },
                  "conversationId": { "type": "string", "maxLength": 120 },
                  "history": {
                    "type": "array",
                    "maxItems": 40,
                    "items": {
                      "type": "object",
                      "required": ["body"],
                      "additionalProperties": false,
                      "properties": {
                        "direction": { "type": "string", "enum": ["inbound", "outbound"] },
                        "sender_type": { "type": "string", "maxLength": 40 },
                        "body": { "type": "string", "maxLength": 700 }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Grounded reply decision", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DraftDecision" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        },
        "x-loresta-scope": "replies:write"
      }
    },
    "/api/v1/agent/handoff": {
      "post": {
        "operationId": "createHandoff",
        "summary": "Queue an existing conversation for creator review",
        "description": "Requires handoffs:write and explicit confirm=true. This does not send a social reply or perform a financial action.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["conversationId", "confirm"],
                "additionalProperties": false,
                "properties": {
                  "conversationId": { "type": "string", "maxLength": 120 },
                  "reason": { "type": "string", "maxLength": 120 },
                  "confirm": { "type": "boolean", "const": true }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Creator handoff queued" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        },
        "x-loresta-scope": "handoffs:write"
      }
    },
    "/api/v1/agent/persona": {
      "get": {
        "operationId": "getPersona",
        "summary": "Get approved non-secret creator persona data",
        "parameters": [{ "name": "profileId", "in": "query", "required": true, "schema": { "type": "string", "maxLength": 120 } }],
        "responses": {
          "200": { "description": "Approved persona, phrases, facts, and offers" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" }
        },
        "x-loresta-scope": "persona:read"
      }
    },
    "/api/v1/agent/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Get monthly agent API quota and privacy-minimal totals",
        "responses": {
          "200": { "description": "Current-period usage" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Error" }
        },
        "x-loresta-scope": "usage:read"
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "Loresta MCP streamable HTTP endpoint",
        "description": "JSON-RPC 2.0 endpoint supporting initialize, ping, tools/list, and tools/call. Tool visibility and execution are restricted by the bearer key scopes.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "200": { "description": "MCP JSON-RPC response" },
          "202": { "description": "MCP notification accepted" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "LorestaAgentKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "lsk_live",
        "description": "A scoped Loresta integration key. The raw value is returned once and only its SHA-256 hash is stored."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": { "type": "string", "minLength": 8, "maxLength": 120, "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]+$" }
      }
    },
    "schemas": {
      "DraftDecision": {
        "type": "object",
        "required": ["ok", "decision"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "decision": {
            "type": "object",
            "required": ["intent", "riskLevel", "confidence", "reply", "requiresCreator"],
            "properties": {
              "intent": { "type": "string" },
              "riskLevel": { "type": "string", "enum": ["safe", "review", "blocked"] },
              "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
              "reply": { "type": "string" },
              "rationale": { "type": "string" },
              "requiresCreator": { "type": "boolean" },
              "mediaAssetId": { "type": "string" }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["ok", "error", "message"],
        "properties": {
          "ok": { "type": "boolean", "const": false },
          "error": { "type": "string" },
          "message": { "type": "string" },
          "requestId": { "type": "string" }
        }
      }
    },
    "responses": {
      "Error": { "description": "Loresta policy or request error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unauthorized": { "description": "Missing, invalid, expired, or revoked Loresta agent key", "headers": { "WWW-Authenticate": { "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
