{
  "openapi": "3.1.0",
  "info": {
    "title": "KefuAgent Agent Gateway",
    "version": "2026-07-12",
    "description": "BYOB gateway: the platform provides context and enforces safety gates; the merchant's own agent does the reasoning. One API key = one workspace. External agents can never trigger sending of high-risk replies. operationId values are the canonical tool names consumed 1:1 by the slice-019 MCP layer and ecosystem packs — renames are breaking changes. Additive fields never bump info.version; breaking changes require a new /v2 path prefix."
  },
  "servers": [{ "url": "https://kefuagents.com/api/gateway/v1" }],
  "security": [{ "apiKey": [] }],
  "paths": {
    "/cards": {
      "get": {
        "operationId": "get_pending_cards",
        "summary": "List pending decision cards (the 014 unified feed read model, workspace-bound)",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["open", "all"],
              "default": "open"
            }
          },
          { "name": "cardType", "in": "query", "schema": { "type": "string" } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "updatedAfter",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" }
          }
        ],
        "responses": {
          "200": {
            "description": "Cards + per-type open stats",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCardsResponse"
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "403": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "429": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/threads/{threadId}/reply-context": {
      "get": {
        "operationId": "get_reply_context",
        "summary": "Everything the platform's own drafting sees for one conversation, plus machine-readable constraints",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "threadId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Reply context bundle",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayReplyContext" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "410": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/threads/{threadId}/drafts": {
      "post": {
        "operationId": "submit_draft",
        "summary": "Submit an externally drafted reply behind the zero-token safety gate (+ bounded high-risk AI recheck, fail closed)",
        "x-scope": "gateway:submit_draft",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "threadId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SubmitDraftRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Accepted into pending_review + reply_approval card",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SubmitDraftResponse" }
              }
            }
          },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/brand-state": {
      "get": {
        "operationId": "get_brand_support_state",
        "summary": "Operational snapshot of the brand's support state (no customer data)",
        "x-scope": "gateway:read",
        "responses": {
          "200": {
            "description": "Brand state",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayBrandState" }
              }
            }
          }
        }
      }
    },
    "/risks": {
      "get": {
        "operationId": "get_open_risks",
        "summary": "Open risks: pending review requests + open high-risk threads (ids and safe titles only)",
        "x-scope": "gateway:read",
        "responses": {
          "200": {
            "description": "Open risks",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GatewayOpenRisks" }
              }
            }
          }
        }
      }
    },
    "/storefront-profile": {
      "get": {
        "operationId": "get_storefront_profile",
        "summary": "What the brand sells: site identity, onboarding state, catalogue rollup, and the merchant's own categories",
        "x-scope": "gateway:read",
        "responses": {
          "200": {
            "description": "Storefront profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayStorefrontProfile"
                }
              }
            }
          }
        }
      }
    },
    "/products": {
      "get": {
        "operationId": "list_products",
        "summary": "Merchant catalogue with the merchant's own taxonomy (product_type / tags / collections) and the main-vs-accessory verdict",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": { "type": "string", "maxLength": 200 }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["main", "accessory", "unknown"]
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Omitted: everything except human-rejected products.",
            "schema": {
              "type": "string",
              "enum": ["pending", "confirmed", "rejected", "uncertain"]
            }
          },
          {
            "name": "focusOnly",
            "in": "query",
            "schema": { "type": "boolean" }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Catalogue page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayProductsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/knowledge/search": {
      "get": {
        "operationId": "search_knowledge",
        "summary": "Search the workspace's published knowledge (brand + industry-standard layers)",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "minLength": 1, "maxLength": 500 }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20,
              "default": 8
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Knowledge snippets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayKnowledgeSearch"
                }
              }
            }
          }
        }
      }
    },
    "/knowledge/proposals": {
      "post": {
        "operationId": "propose_knowledge",
        "summary": "Propose a knowledge candidate — always human-confirmed, never auto-published",
        "x-scope": "gateway:submit_draft",
        "x-idempotent": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProposeKnowledgeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pending candidate",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposeKnowledgeResponse"
                }
              }
            }
          },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/context-updates": {
      "post": {
        "operationId": "submit_context_update",
        "summary": "Store a raw pending operational context digest (zero platform AI processing)",
        "x-scope": "gateway:submit_draft",
        "x-idempotent": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ContextUpdateRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pending digest",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContextUpdateResponse"
                }
              }
            }
          },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/review-requests": {
      "post": {
        "operationId": "create_review_request",
        "summary": "Open a human review request through the existing escalation pipeline",
        "x-scope": "gateway:submit_draft",
        "x-idempotent": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ReviewRequestRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pending review request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReviewRequestResponse"
                }
              }
            }
          },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/cards/{taskId}/decision": {
      "post": {
        "operationId": "approve_or_reject_reply",
        "summary": "Approve (gateway:approve, off by default) or reject a pending card via the 014 executor — high-risk approve is always refused for keys",
        "x-scope": "gateway:approve (approve) / gateway:submit_draft (reject)",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/DecisionRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "014 AgentTaskActionResponse, verbatim",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentTaskActionResponse"
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/cards/{taskId}/instruct": {
      "post": {
        "operationId": "instruct_rewrite",
        "summary": "Chinese-instruction rewrite of a draft — no replacement body-text field exists",
        "x-scope": "gateway:submit_draft",
        "x-idempotent": true,
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/InstructRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "014 AgentTaskActionResponse with result kind 'rewritten'",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentTaskActionResponse"
                }
              }
            }
          },
          "409": { "$ref": "#/components/responses/GatewayErrorResponse" },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/webhooks": {
      "post": {
        "operationId": "register_webhook",
        "summary": "Register a signed webhook delivery target (secret shown exactly once)",
        "x-scope": "gateway:read",
        "x-idempotent": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription + one-time secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterWebhookResponse"
                }
              }
            }
          },
          "422": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      },
      "get": {
        "operationId": "list_webhooks",
        "summary": "List the workspace's subscriptions (secrets never included)",
        "x-scope": "gateway:read",
        "responses": {
          "200": {
            "description": "Subscriptions without secrets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListWebhooksResponse"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{subscriptionId}": {
      "delete": {
        "operationId": "delete_webhook",
        "summary": "Delete a subscription; delivery stops immediately",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "204": { "description": "Deleted" },
          "404": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    },
    "/webhooks/{subscriptionId}/rotate-secret": {
      "post": {
        "operationId": "rotate_webhook_secret",
        "summary": "Rotate the signing secret; the new secret is shown exactly once",
        "x-scope": "gateway:read",
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "New secret",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "const": true },
                    "secret": { "type": "string" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/GatewayErrorResponse" }
        }
      }
    }
  },
  "webhooks": {
    "task.created": {
      "post": {
        "summary": "Frozen 014 envelope (specs/014-agent-task-feed/contracts/agent-task-webhook.md): thin ids-only payload, HMAC v1 signature over '{timestamp}.{rawBody}', 300s anti-replay, at-least-once, receiver dedupes by X-KefuAgent-Event-Id",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AgentTaskWebhookEvent" }
            }
          }
        },
        "responses": { "2XX": { "description": "Acknowledge within 10s" } }
      }
    },
    "task.updated": {
      "post": {
        "summary": "Same envelope as task.created with previousStatus set",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AgentTaskWebhookEvent" }
            }
          }
        },
        "responses": { "2XX": { "description": "Acknowledge within 10s" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Workspace-bound gateway key. Every mutating operation additionally requires an Idempotency-Key header (8-128 chars) or body idempotencyKey. Optional X-Kefu-Trace-Id is echoed and audited."
      }
    },
    "responses": {
      "GatewayErrorResponse": {
        "description": "GatewayError body; violations[] only on DRAFT_REJECTED; Retry-After header on 429",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/GatewayError" }
          }
        }
      }
    },
    "schemas": {
      "GatewayError": {
        "type": "object",
        "required": ["success", "code", "message", "traceId"],
        "properties": {
          "success": { "const": false },
          "code": {
            "type": "string",
            "enum": [
              "UNAUTHENTICATED",
              "FORBIDDEN_WORKSPACE",
              "KEY_SCOPE_MISSING",
              "HIGH_RISK_REQUIRES_HUMAN",
              "NOT_FOUND",
              "IDEMPOTENCY_CONFLICT",
              "ACTION_IN_PROGRESS",
              "VERSION_CONFLICT",
              "TASK_ALREADY_RESOLVED",
              "RESOURCE_GONE",
              "DRAFT_REJECTED",
              "STALE_CONTEXT",
              "SEND_BLOCKED",
              "VALIDATION_FAILED",
              "WEBHOOK_URL_INVALID",
              "WEBHOOK_LIMIT_REACHED",
              "RATE_LIMITED",
              "ACTION_NOT_AVAILABLE",
              "INSTRUCTION_INVALID",
              "UPSTREAM_FAILED"
            ]
          },
          "message": { "type": "string" },
          "traceId": { "type": "string" },
          "retryAfterSec": { "type": "integer" },
          "violations": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/GateViolation" }
          }
        }
      },
      "GateViolation": {
        "type": "object",
        "required": ["code", "messageZh"],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "completed_action_claim",
              "invented_tracking_number",
              "unbacked_commitment",
              "policy_sensitive_unsupported",
              "oversized_content",
              "unsupported_format",
              "high_risk_recheck_unavailable",
              "high_risk_recheck_failed"
            ]
          },
          "messageZh": { "type": "string" },
          "evidence": { "type": "string", "maxLength": 120 },
          "retryable": { "type": "boolean" }
        }
      },
      "AgentTaskCard": {
        "type": "object",
        "description": "The slice-014 decision-card read model, verbatim (payload already privacy-safe).",
        "required": [
          "id",
          "cardType",
          "status",
          "riskLevel",
          "title",
          "version"
        ],
        "properties": {
          "id": { "type": "string" },
          "cardType": {
            "type": "string",
            "enum": [
              "reply_approval",
              "risk_escalation",
              "knowledge_confirm",
              "ai_question",
              "sync_failure",
              "low_credit",
              "delegation_proposal",
              "batch_confirm"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "snoozed",
              "done",
              "dismissed",
              "superseded",
              "expired"
            ]
          },
          "riskLevel": { "type": "string", "enum": ["normal", "high"] },
          "priority": { "type": "integer" },
          "title": { "type": "string" },
          "summaryZh": { "type": "string" },
          "version": { "type": "integer" },
          "availableActions": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["approve", "reject", "instruct", "snooze", "open_in_web"]
            }
          }
        },
        "additionalProperties": true
      },
      "GatewayCardsResponse": {
        "type": "object",
        "required": ["success", "items", "nextCursor", "stats"],
        "properties": {
          "success": { "const": true },
          "items": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/AgentTaskCard" }
          },
          "nextCursor": { "type": ["string", "null"] },
          "stats": {
            "type": "object",
            "properties": {
              "byType": {
                "type": "object",
                "additionalProperties": { "type": "integer" }
              },
              "openTotal": { "type": "integer" }
            }
          }
        }
      },
      "GatewayReplyContext": {
        "type": "object",
        "required": [
          "success",
          "thread",
          "contextVersion",
          "transcript",
          "knowledge",
          "agentRules",
          "timeAnchor",
          "constraints"
        ],
        "properties": {
          "success": { "const": true },
          "thread": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "subject": { "type": "string" },
              "status": { "type": "string" },
              "riskLevel": { "type": "string", "enum": ["normal", "high"] },
              "needsInfo": { "type": "boolean" },
              "missingInfoSummary": { "type": ["string", "null"] },
              "customer": {
                "type": "object",
                "properties": { "emailMasked": { "type": ["string", "null"] } }
              }
            }
          },
          "contextVersion": {
            "type": "string",
            "description": "Latest inbound support_message.id — echo into submit_draft.declaredContextVersion."
          },
          "transcript": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "direction": {
                  "type": "string",
                  "enum": ["inbound", "outbound"]
                },
                "channel": { "type": ["string", "null"] },
                "text": {
                  "type": "string",
                  "description": "cleanText only — quoted history stripped at ingest"
                },
                "at": { "type": "string", "format": "date-time" }
              }
            }
          },
          "orderContext": {
            "type": ["object", "null"],
            "description": "DraftOrderContext; lookup_status semantics are authoritative — 'matched' only permits citing the returned orders.",
            "additionalProperties": true
          },
          "knowledge": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": { "type": "string" },
                "body": { "type": "string" },
                "source": { "type": "string", "enum": ["brand", "standard"] },
                "missingBrandValues": {
                  "type": "array",
                  "items": { "type": "string" }
                },
                "media": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": { "type": "string" },
                      "url": { "type": "string" },
                      "title": { "type": "string" }
                    }
                  }
                }
              }
            }
          },
          "agentRules": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "scope": { "type": "string" },
                "title": { "type": "string" },
                "ruleZh": { "type": "string" },
                "ruleEn": { "type": ["string", "null"] }
              }
            }
          },
          "attachmentContext": {
            "type": ["object", "null"],
            "properties": {
              "summary": { "type": "string" },
              "totalCount": { "type": "integer" },
              "imageCount": { "type": "integer" },
              "videoCount": { "type": "integer" },
              "fileCount": { "type": "integer" },
              "visionReviewCount": { "type": "integer" },
              "usableVisualReviewCount": { "type": "integer" },
              "needsHumanVisualReview": { "type": "boolean" }
            }
          },
          "timeAnchor": {
            "type": "object",
            "properties": {
              "currentDate": { "type": "string" },
              "timeZone": { "type": "string" }
            }
          },
          "constraints": {
            "$ref": "#/components/schemas/GatewayDraftConstraints"
          }
        }
      },
      "GatewayDraftConstraints": {
        "type": "object",
        "properties": {
          "forbiddenCommitments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "completed_action_claim",
                    "invented_tracking_number",
                    "unbacked_commitment",
                    "order_fact_invention"
                  ]
                },
                "descriptionZh": { "type": "string" },
                "description": { "type": "string" }
              }
            }
          },
          "highRiskCategories": {
            "type": "array",
            "items": { "type": "string" }
          },
          "languagePolicy": {
            "type": "object",
            "properties": {
              "reply": { "const": "match_customer_language" },
              "fallback": { "const": "en" }
            }
          },
          "format": {
            "type": "object",
            "properties": {
              "plainTextOnly": { "const": true },
              "maxChars": { "type": "integer" }
            }
          },
          "policyNote": { "type": "string" }
        }
      },
      "SubmitDraftRequest": {
        "type": "object",
        "required": ["idempotencyKey", "bodyText", "declaredContextVersion"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "bodyText": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000,
            "description": "Plain text only"
          },
          "declaredContextVersion": {
            "type": "string",
            "description": "contextVersion echoed from get_reply_context"
          },
          "agentLabel": { "type": "string", "maxLength": 120 }
        }
      },
      "SubmitDraftResponse": {
        "type": "object",
        "required": ["success", "replayed", "verdict"],
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "verdict": {
            "type": "object",
            "properties": {
              "result": { "const": "accepted" },
              "recheck": { "type": "string", "enum": ["skipped", "passed"] },
              "replyDraftId": { "type": "string" },
              "taskId": { "type": ["string", "null"] }
            }
          }
        }
      },
      "GatewayBrandState": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "workspace": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "timeZone": { "type": "string" },
              "currentDate": { "type": "string" }
            }
          },
          "cards": {
            "type": "object",
            "properties": {
              "byType": {
                "type": "object",
                "additionalProperties": { "type": "integer" }
              },
              "openTotal": { "type": "integer" }
            }
          },
          "inbox": {
            "type": ["object", "null"],
            "properties": {
              "status": { "type": "string" },
              "sendMode": {
                "type": "string",
                "enum": ["test_only", "production"]
              },
              "shadowMode": { "type": "boolean" }
            }
          },
          "automation": {
            "type": ["object", "null"],
            "properties": { "autoReplyEnabled": { "type": "boolean" } }
          },
          "credits": {
            "type": "object",
            "properties": {
              "canUseAi": { "type": "boolean" },
              "lowCredit": { "type": "boolean" }
            }
          },
          "knowledge": {
            "type": "object",
            "properties": {
              "publishedArticles": { "type": "integer" },
              "pendingCandidates": { "type": "integer" }
            }
          }
        }
      },
      "GatewayOpenRisks": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "kind": {
                  "type": "string",
                  "enum": ["review_request", "high_risk_thread"]
                },
                "requestType": { "type": "string" },
                "title": { "type": "string" },
                "threadId": { "type": ["string", "null"] },
                "chatSessionId": { "type": ["string", "null"] },
                "openedAt": { "type": "string", "format": "date-time" }
              }
            }
          }
        }
      },
      "GatewayKnowledgeSearch": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": { "type": "string" },
                "body": { "type": "string" },
                "source": { "type": "string", "enum": ["brand", "standard"] },
                "missingBrandValues": {
                  "type": "array",
                  "items": { "type": "string" }
                },
                "sourceUrl": {
                  "type": ["string", "null"],
                  "description": "Page this answer was learned from; null for the platform standard layer."
                },
                "lastVerifiedAt": {
                  "type": ["string", "null"],
                  "description": "Last time the source page was re-verified; null when never recorded."
                },
                "verification": {
                  "type": "string",
                  "enum": ["fresh", "stale"],
                  "description": "\"stale\" = the source page changed after this answer was written."
                },
                "provenance": { "type": "string" },
                "links": {
                  "type": "array",
                  "description": "Real help/FAQ pages this reply may LINK to instead of restating them.",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": { "type": "string" },
                      "url": { "type": "string" },
                      "title": { "type": ["string", "null"] }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "GatewayStorefrontProfile": {
        "type": "object",
        "description": "Everything onboarding derived from the merchant's single website URL.",
        "properties": {
          "success": { "const": true },
          "site": {
            "type": "object",
            "properties": {
              "websiteUrl": { "type": ["string", "null"] },
              "websiteDomain": { "type": ["string", "null"] },
              "platform": {
                "type": ["string", "null"],
                "description": "shopify | woocommerce | bigcommerce | wix | squarespace | unknown"
              }
            }
          },
          "onboarding": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "not_started",
                  "inbox_connected",
                  "range_selected",
                  "processing",
                  "kb_review",
                  "completed",
                  "failed"
                ]
              },
              "readyForLiveInbox": { "type": "boolean" }
            }
          },
          "catalogue": {
            "type": "object",
            "properties": {
              "total": { "type": "integer" },
              "confirmed": { "type": "integer" },
              "focus": { "type": "integer" },
              "byKind": {
                "type": "object",
                "additionalProperties": { "type": "integer" }
              },
              "byKindSource": {
                "type": "object",
                "additionalProperties": { "type": "integer" },
                "description": "\"merchant\" = the merchant's own taxonomy decided the kind, outranking our keyword heuristic and the model."
              }
            }
          },
          "merchantCategories": {
            "type": "object",
            "description": "The MERCHANT's own category labels, most-used first.",
            "properties": {
              "productTypes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": { "type": "string" },
                    "count": { "type": "integer" }
                  }
                }
              },
              "collections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": { "type": "string" },
                    "count": { "type": "integer" }
                  }
                }
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "label": { "type": "string" },
                    "count": { "type": "integer" }
                  }
                }
              },
              "sampled": {
                "type": "boolean",
                "description": "True when the catalogue exceeded the label sample cap."
              }
            }
          }
        }
      },
      "GatewayProductsResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "title": { "type": "string" },
                "productUrl": { "type": ["string", "null"] },
                "imageUrl": { "type": ["string", "null"] },
                "priceSnapshot": {
                  "type": ["string", "null"],
                  "description": "Price string as captured; may be stale. Never quote it as the current price."
                },
                "currency": { "type": ["string", "null"] },
                "productType": {
                  "type": ["string", "null"],
                  "description": "The merchant's own Shopify product_type, verbatim."
                },
                "tags": { "type": "array", "items": { "type": "string" } },
                "collections": {
                  "type": "array",
                  "items": { "type": "string" },
                  "description": "Handles of the merchant collections this product belongs to."
                },
                "kind": {
                  "type": "string",
                  "enum": ["main", "accessory", "unknown"]
                },
                "kindSource": {
                  "type": "string",
                  "enum": ["heuristic", "ai", "user", "merchant"]
                },
                "status": {
                  "type": "string",
                  "enum": ["pending", "confirmed", "rejected", "uncertain"]
                },
                "isFocus": { "type": "boolean" },
                "provider": { "type": "string" }
              }
            }
          },
          "nextCursor": { "type": ["string", "null"] }
        }
      },
      "ProposeKnowledgeRequest": {
        "type": "object",
        "required": ["idempotencyKey", "title", "question", "proposedAnswer"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "title": { "type": "string", "minLength": 1, "maxLength": 160 },
          "question": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "proposedAnswer": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "category": { "type": "string", "default": "general" },
          "sourceNote": { "type": "string", "maxLength": 500 }
        }
      },
      "ProposeKnowledgeResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "candidateId": { "type": "string" },
          "status": { "const": "pending" }
        }
      },
      "ContextUpdateRequest": {
        "type": "object",
        "required": ["idempotencyKey", "sourceName", "rawSummaryZh"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "sourceName": { "type": "string", "minLength": 1, "maxLength": 80 },
          "digestDate": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "Defaults to merchant-local today"
          },
          "rawSummaryZh": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          }
        }
      },
      "ContextUpdateResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "digestId": { "type": "string" },
          "status": { "const": "pending" }
        }
      },
      "ReviewRequestRequest": {
        "type": "object",
        "required": ["idempotencyKey", "draftId"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "draftId": { "type": "string" },
          "summaryZh": { "type": "string", "maxLength": 2000 },
          "escalationReason": { "type": "string", "maxLength": 500 }
        }
      },
      "ReviewRequestResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "requestId": { "type": "string" },
          "platform": { "type": ["string", "null"] },
          "channelName": { "type": ["string", "null"] }
        }
      },
      "DecisionRequest": {
        "type": "object",
        "required": ["idempotencyKey", "decision"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "decision": { "type": "string", "enum": ["approve", "reject"] },
          "expectedVersion": {
            "type": "integer",
            "description": "Required for approve (014 VERSION_CONFLICT semantics)"
          },
          "note": {
            "type": "string",
            "description": "Reject note where the card type requires it"
          }
        }
      },
      "InstructRequest": {
        "type": "object",
        "required": ["idempotencyKey", "instruction"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "instruction": {
            "type": "object",
            "required": ["textZh", "scope"],
            "properties": {
              "textZh": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2000,
                "description": "Chinese supervision language — there is NO field for replacement body text"
              },
              "scope": {
                "type": "string",
                "enum": ["single_reply", "similar_cases", "global_rule"]
              }
            }
          },
          "expectedVersion": { "type": "integer" }
        }
      },
      "AgentTaskActionResponse": {
        "type": "object",
        "description": "The slice-014 action response, verbatim.",
        "required": ["success", "replayed", "task", "result"],
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "task": { "$ref": "#/components/schemas/AgentTaskCard" },
          "result": { "type": "object", "additionalProperties": true }
        }
      },
      "RegisterWebhookRequest": {
        "type": "object",
        "required": ["idempotencyKey", "url"],
        "properties": {
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 128
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "https:// only; SSRF-checked (no private/loopback/link-local, no redirects followed)"
          },
          "eventTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["task.created", "task.updated"]
            },
            "description": "Default: both"
          }
        }
      },
      "RegisterWebhookResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "replayed": { "type": "boolean" },
          "subscription": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "url": { "type": "string" },
              "eventTypes": { "type": "array", "items": { "type": "string" } },
              "status": { "type": "string" },
              "createdAt": { "type": "string", "format": "date-time" }
            }
          },
          "secret": {
            "type": "string",
            "description": "Shown EXACTLY ONCE. Never retrievable again through any API or UI."
          }
        }
      },
      "ListWebhooksResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "url": { "type": "string" },
                "eventTypes": {
                  "type": "array",
                  "items": { "type": "string" }
                },
                "status": {
                  "type": "string",
                  "enum": ["active", "suspended", "disabled"]
                },
                "orphaned": { "type": "boolean" },
                "consecutiveFailures": { "type": "integer" },
                "lastSuccessAt": { "type": ["string", "null"] },
                "lastFailureAt": { "type": ["string", "null"] },
                "createdAt": { "type": "string" }
              }
            }
          }
        }
      },
      "AgentTaskWebhookEvent": {
        "type": "object",
        "description": "Frozen in specs/014-agent-task-feed/contracts/agent-task-webhook.md — ids, type, status, riskLevel, priority, safe title, version, source ids only. No summaries, no customer identifiers, no draft text.",
        "required": [
          "id",
          "type",
          "apiVersion",
          "createdAt",
          "workspaceId",
          "traceId",
          "data"
        ],
        "properties": {
          "id": { "type": "string" },
          "type": {
            "type": "string",
            "enum": ["task.created", "task.updated"]
          },
          "apiVersion": { "const": "2026-07-12" },
          "createdAt": { "type": "string", "format": "date-time" },
          "workspaceId": { "type": "string" },
          "traceId": { "type": "string" },
          "data": {
            "type": "object",
            "properties": {
              "task": {
                "type": "object",
                "properties": {
                  "id": { "type": "string" },
                  "cardType": { "type": "string" },
                  "status": { "type": "string" },
                  "riskLevel": { "type": "string", "enum": ["normal", "high"] },
                  "priority": { "type": "integer" },
                  "title": { "type": "string" },
                  "version": { "type": "integer" },
                  "queuedAt": { "type": "string" },
                  "createdAt": { "type": "string" },
                  "updatedAt": { "type": "string" },
                  "source": {
                    "type": "object",
                    "properties": {
                      "threadId": { "type": ["string", "null"] },
                      "replyDraftId": { "type": ["string", "null"] },
                      "knowledgeCandidateId": { "type": ["string", "null"] },
                      "reviewRequestId": { "type": ["string", "null"] },
                      "chatSessionId": { "type": ["string", "null"] },
                      "inboxConnectionId": { "type": ["string", "null"] }
                    }
                  }
                }
              },
              "previousStatus": { "type": ["string", "null"] },
              "causedBy": { "type": ["object", "null"] }
            }
          }
        }
      }
    }
  }
}
