{
  "openapi": "3.0.3",
  "info": {
    "title": "FacePick local developer API",
    "version": "1.1.0",
    "description": "Machine-readable contract for the six implemented application Bearer endpoints only. Same local PostgreSQL identities and immutable business lineage. No production payment, KYC, model generation, automatic review or revenue settlement is claimed. Cookie console/admin APIs and Webhook delivery schemas are outside this document, not outside the integration goal. Use keys only in a private server-side process; never enter them into public documentation sites."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:3110",
      "description": "Ordinary local integration preview. Automated tests use an isolated server/database on port 3111, overriding this server URL."
    }
  ],
  "security": [
    {
      "ApplicationKey": []
    }
  ],
  "paths": {
    "/api/developer/whoami": {
      "get": {
        "operationId": "getApplicationIdentity",
        "summary": "Read application identity",
        "description": "Reads current key ownership; no license consumption or generation.",
        "responses": {
          "200": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/developer/faces": {
      "get": {
        "operationId": "searchFaces",
        "summary": "Search published public face assets",
        "description": "Returns at most 100 safe records, sorted by FaceID. Search matches name, description or FaceID literally; no pagination parameters. Querying does not grant usage rights. Authenticated result/failure is recorded in API usage; storage failure fails the request.",
        "responses": {
          "200": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FacesResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, scope or media. Runtime rights/state checks are additional to schema validation.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Local/test sandbox unavailable; production providers are not configured.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Optional literal search, trimmed by server.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ]
      }
    },
    "/api/developer/faces/{faceId}": {
      "get": {
        "operationId": "getFace",
        "summary": "Read a published public asset",
        "description": "Only published safe DTO; nonexistent, paused and invalid IDs return 404. No private identity/capture data. Querying does not grant usage rights.",
        "responses": {
          "200": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FaceResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Object not found, unavailable, or not owned by this application.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Local/test sandbox unavailable; production providers are not configured.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "faceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/developer/license-uses": {
      "post": {
        "operationId": "useLicense",
        "summary": "Consume one valid licensed use",
        "description": "Requires paid active license for this exact Application and published asset. Scope and training permission checked independently. Successful first use consumes one count atomically. Persist idempotencyKey before sending: same Application + idempotencyKey + payload replays the original receipt without consuming again, including through another valid Key of that Application; different payload conflicts. Receipt is not a generation task. Replaying history after suspension/expiry does not authorize new use. JSON body at most 16 KiB. Revoked keys cannot replay.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseUseInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LicenseUseResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON request body.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Untrusted Origin on write requests. Server-to-server Bearer requests may omit Origin; a supplied Origin must match the configured service origin.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Object not found, unavailable, or not owned by this application.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State or idempotency conflict; use may be inactive or quota exhausted. Query original state before retrying a write; never change a stable key just to bypass a conflict.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "JSON body exceeds endpoint limit.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "JSON content type required.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, scope or media. Runtime rights/state checks are additional to schema validation.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Local/test sandbox unavailable; production providers are not configured.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/developer/contents": {
      "post": {
        "operationId": "submitContent",
        "summary": "Return actual content for a use",
        "description": "Exact Application required. One Content per non-training Use; image/video MIME must match the use purpose. Actual decoded file at most 5 MiB, JSON body at most 7 MiB. No extra quota consumption. First creation is UNDER_REVIEW; same application/idempotencyKey and same content replay its current status (possibly APPROVED or REJECTED) with 201. Different payload or duplicate Use conflicts. Manual approval is not public publishing or real-world rights clearance. Store a stable idempotencyKey and reuse unchanged parameters on uncertain retries.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON request body.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Untrusted Origin on write requests. Server-to-server Bearer requests may omit Origin; a supplied Origin must match the configured service origin.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Object not found, unavailable, or not owned by this application.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "State or idempotency conflict; use may be inactive or quota exhausted. Query original state before retrying a write; never change a stable key just to bypass a conflict.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "JSON body exceeds endpoint limit.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "JSON content type required.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, scope or media. Runtime rights/state checks are additional to schema validation.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Local/test sandbox unavailable; production providers are not configured.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/developer/faces/page": {
      "get": {
        "operationId": "searchFacesPage",
        "summary": "Page through published public assets",
        "description": "Returns items and nextCursor, sorted by FaceID. Repeat with the same q and returned cursor until nextCursor is null. Default limit20/max100. Every page authenticates the current Application Key and logs the attempt; log storage failure fails closed. Cursor binds the trimmed search, not an authorization grant. Each page queries current PUBLISHED assets, not a frozen snapshot across pages.",
        "responses": {
          "200": {
            "description": "Successful operation. Data includes sandbox records, not commercial likeness rights.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FacesPageResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: missing, invalid or revoked API Key. Cookie does not replace Bearer.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, scope or media. Runtime rights/state checks are additional to schema validation.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal failure; safe message and requestId only.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Local/test sandbox unavailable; production providers are not configured.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt; may differ from an idempotently replayed record's original requestId.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Optional literal search, trimmed by server.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 1000
            },
            "description": "Opaque cursor from previous page; preserve the same q."
          }
        ]
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getLiveness",
        "summary": "Public liveness probe",
        "description": "Process liveness only; no dependency checks, no authentication, no internal details.",
        "security": [],
        "responses": {
          "200": {
            "description": "Process is up.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LivenessResponse"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/readiness": {
      "get": {
        "operationId": "getReadiness",
        "summary": "Administrator readiness check",
        "description": "Checks configuration and PostgreSQL. Redis and storage are reserved slots reporting not_configured until wired.",
        "security": [
          {
            "AdminSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "All required checks pass.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHENTICATED: no valid session.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "FORBIDDEN: not an administrator.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "A required check failed.",
            "headers": {
              "X-Request-ID": {
                "description": "Correlation ID for this HTTP attempt.",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApplicationKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Opaque fp_ API Key created for an Application, not a JWT or browser session. Full value shown once."
      },
      "AdminSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "facepic_session",
        "description": "Console session cookie of an Admin or SuperAdmin user."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code",
          "message",
          "requestId"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          },
          "details": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "Identity": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "applicationId",
          "developerId"
        ],
        "properties": {
          "applicationId": {
            "type": "string",
            "format": "uuid"
          },
          "developerId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Policy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "purposes",
          "channels",
          "territories",
          "termMonths",
          "usageCount",
          "trainingAllowed",
          "exclusive",
          "requireContentReview"
        ],
        "properties": {
          "purposes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "image",
                "video"
              ]
            }
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "online",
                "offline"
              ]
            }
          },
          "territories": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "CN",
                "GLOBAL"
              ]
            }
          },
          "termMonths": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60
          },
          "usageCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100000
          },
          "trainingAllowed": {
            "type": "boolean"
          },
          "exclusive": {
            "type": "boolean"
          },
          "requireContentReview": {
            "type": "boolean"
          }
        }
      },
      "Face": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "faceId",
          "name",
          "description",
          "policy",
          "media",
          "sandbox"
        ],
        "properties": {
          "faceId": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "policy": {
            "$ref": "#/components/schemas/Policy"
          },
          "media": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "sampleKey"
              ],
              "properties": {
                "sampleKey": {
                  "type": "string"
                }
              }
            }
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        }
      },
      "LicenseUseInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "licenseId",
          "purpose",
          "channel",
          "territory",
          "training",
          "idempotencyKey"
        ],
        "properties": {
          "licenseId": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "online",
              "offline"
            ]
          },
          "territory": {
            "type": "string",
            "enum": [
              "CN",
              "GLOBAL"
            ]
          },
          "training": {
            "type": "boolean"
          },
          "idempotencyKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9_-]+$"
          }
        }
      },
      "LicenseUse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "licenseId",
          "orderId",
          "faceId",
          "applicationId",
          "requestId",
          "purpose",
          "channel",
          "territory",
          "training",
          "createdAt",
          "sandbox"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "licenseId": {
            "type": "string",
            "format": "uuid"
          },
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "faceId": {
            "type": "string",
            "format": "uuid"
          },
          "applicationId": {
            "type": "string",
            "format": "uuid"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "online",
              "offline"
            ]
          },
          "territory": {
            "type": "string",
            "enum": [
              "CN",
              "GLOBAL"
            ]
          },
          "training": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        }
      },
      "ContentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "useId",
          "title",
          "mimeType",
          "dataBase64",
          "idempotencyKey"
        ],
        "properties": {
          "useId": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Trimmed nonempty title; disallowed control characters are rejected."
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "video/mp4"
            ]
          },
          "dataBase64": {
            "type": "string",
            "format": "byte",
            "minLength": 4,
            "maxLength": 6990508,
            "description": "Canonical standard Base64 of actual file bytes, not a URL/data URL. Decoded bytes at most 5 MiB; JSON body at most 7 MiB. Basic media signatures checked, not malware scanning."
          },
          "idempotencyKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9_-]+$"
          }
        }
      },
      "Content": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "useId",
          "licenseId",
          "orderId",
          "faceId",
          "applicationId",
          "title",
          "status",
          "requireContentReview",
          "automaticReview",
          "mimeType",
          "byteCount",
          "sha256",
          "reason",
          "reviewedAt",
          "createdAt",
          "requestId",
          "useRequestId",
          "sandbox"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "useId": {
            "type": "string",
            "format": "uuid"
          },
          "licenseId": {
            "type": "string",
            "format": "uuid"
          },
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "faceId": {
            "type": "string",
            "format": "uuid"
          },
          "applicationId": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "UNDER_REVIEW",
              "APPROVED",
              "REJECTED"
            ]
          },
          "requireContentReview": {
            "type": "boolean"
          },
          "automaticReview": {
            "type": "string",
            "enum": [
              "NOT_CONFIGURED"
            ]
          },
          "mimeType": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "video/mp4"
            ]
          },
          "byteCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5242880
          },
          "sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "reviewedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          },
          "useRequestId": {
            "type": "string",
            "format": "uuid"
          },
          "sandbox": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        }
      },
      "IdentityResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Identity"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "FacesResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Face"
            },
            "maxItems": 100
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "FaceResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Face"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "LicenseUseResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LicenseUse"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ContentResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Content"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "FacesPageResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "items",
              "nextCursor"
            ],
            "properties": {
              "items": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/Face"
                }
              },
              "nextCursor": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "CheckResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "durationMs"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "unavailable",
              "not_configured"
            ]
          },
          "durationMs": {
            "type": "integer",
            "minimum": 0
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Liveness": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "service",
          "now"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "service": {
            "type": "string"
          },
          "now": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LivenessResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Liveness"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Readiness": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "checks"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "unavailable"
            ]
          },
          "checks": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "config",
              "database",
              "redis",
              "storage"
            ],
            "properties": {
              "config": {
                "$ref": "#/components/schemas/CheckResult"
              },
              "database": {
                "$ref": "#/components/schemas/CheckResult"
              },
              "redis": {
                "$ref": "#/components/schemas/CheckResult"
              },
              "storage": {
                "$ref": "#/components/schemas/CheckResult"
              }
            }
          }
        }
      },
      "ReadinessResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "requestId"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Readiness"
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          }
        }
      }
    }
  }
}
