{
  "openapi": "3.0.0",
  "info": {
    "title": "Hunter Platform API",
    "version": "1.8.0",
    "description": "猎头中介 API 平台 — HTTP-only API for external AI agents. Detailed docs in /v1/skill.md."
  },
  "servers": [
    {
      "url": "https://qing3.top",
      "description": "Production"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local dev"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key issued by POST /v1/auth/register. Pass as `Authorization: Bearer hp_live_...`."
      },
      "AdminBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Admin shared password (ADMIN_PASSWORD env var, bcrypt-hashed server-side). Pass as `Authorization: Bearer <ADMIN_PASSWORD>`."
      }
    },
    "schemas": {
      "Ok": {
        "type": "object",
        "required": [
          "ok",
          "data"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "data": {}
        }
      },
      "Err": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHORIZED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "INVALID_PARAMS",
                  "INVALID_STATE",
                  "DUPLICATE_REQUEST",
                  "CONTACT_TAKEN",
                  "INSUFFICIENT_QUOTA",
                  "RATE_LIMITED",
                  "INVALID_CHARSET",
                  "INVALID_CONTENT_TYPE",
                  "INVALID_JSON",
                  "PAYLOAD_TOO_LARGE",
                  "NOT_IMPLEMENTED",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "UserType": {
        "type": "string",
        "enum": [
          "candidate",
          "headhunter",
          "employer"
        ]
      },
      "UserStatus": {
        "type": "string",
        "enum": [
          "active",
          "suspended",
          "deleted"
        ]
      },
      "UserPublic": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "user_type": {
            "$ref": "#/components/schemas/UserType"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "quota_per_day": {
            "type": "integer"
          },
          "quota_used": {
            "type": "integer"
          },
          "quota_reset_at": {
            "type": "string",
            "format": "date-time"
          },
          "reputation": {
            "type": "integer"
          },
          "status": {
            "$ref": "#/components/schemas/UserStatus"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ActionHistoryEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "user_id": {
            "type": "string"
          },
          "action_type": {
            "type": "string"
          },
          "target_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "target_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "request_summary_json": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_summary_json": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ]
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Notification": {
        "type": "object",
        "description": "In-site system notification (polling-based, 30-day TTL, user-scoped)",
        "properties": {
          "id": {
            "type": "string",
            "description": "notif_<12-hex>"
          },
          "category": {
            "type": "string",
            "enum": [
              "recommendation_accepted",
              "recommendation_rejected",
              "unlock_granted",
              "candidate_viewed",
              "placement_confirmed",
              "commission_paid"
            ]
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": [
              "string",
              "null"
            ]
          },
          "payload": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          },
          "read_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden for this user type / scope",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "InvalidParams": {
        "description": "Validation error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "ContactTaken": {
        "description": "Contact already in use (same role within 24h, or cross-role active)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "InsufficientQuota": {
        "description": "Daily quota exhausted",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      },
      "NotImplemented": {
        "description": "Endpoint reserved for a future version",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Err"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "summary": "Health check (public)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok"
          }
        }
      }
    },
    "/v1/capabilities": {
      "get": {
        "summary": "Domain Capability Sets discovery (Phase 4, public) — 列出所有能力集(角色 + 端点 + 配额 + 前置条件 + 副作用)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/capabilities/me": {
      "get": {
        "summary": "当前用户的可用能力列表(Phase 4) — 含 quota 剩余和 available/reason",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/ping": {
      "get": {
        "summary": "Admin health check (requires admin bearer token)",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/auth/login": {
      "post": {
        "summary": "Admin login (returns api_key; rotates existing key)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login success; data.api_key is the new bearer token"
          },
          "400": {
            "description": "Invalid params"
          },
          "401": {
            "description": "Invalid email or password"
          },
          "403": {
            "description": "Admin account suspended"
          }
        }
      }
    },
    "/v1/admin/auth/rotate-key": {
      "post": {
        "summary": "Rotate admin api_key (invalidates old)",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "New key"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/me": {
      "get": {
        "summary": "Current admin info",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Admin info"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/dashboard/stats": {
      "get": {
        "summary": "Platform dashboard statistics — Sub-B: adds today_new_users + trend_30d[30]",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Dashboard stats (includes today_new_users int + trend_30d int[30])"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/users": {
      "get": {
        "summary": "List users (admin) — Sub-B: paginated envelope with offset/keyword",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "user_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "keyword",
            "in": "query",
            "description": "LIKE name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User list (paginated envelope: data + pagination)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "total",
                        "page",
                        "pageSize",
                        "has_more"
                      ],
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "page": {
                          "type": "integer"
                        },
                        "pageSize": {
                          "type": "integer"
                        },
                        "has_more": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid page or pageSize"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/users/{id}/suspend": {
      "post": {
        "summary": "Suspend user",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User suspended"
          },
          "400": {
            "description": "Invalid params"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "User not found"
          }
        }
      }
    },
    "/v1/admin/users/{id}/unsuspend": {
      "post": {
        "summary": "Unsuspend user",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "User unsuspended"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "User not found"
          }
        }
      }
    },
    "/v1/admin/users/{id}/adjust-quota": {
      "post": {
        "summary": "Adjust user quota",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "new_quota"
                ],
                "properties": {
                  "new_quota": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quota adjusted"
          },
          "400": {
            "description": "Invalid params"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "User not found"
          }
        }
      }
    },
    "/v1/admin/candidates": {
      "get": {
        "summary": "List candidates (admin) — Sub-B: paginated envelope with masked PII",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "in_pool",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "unlock_status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "keyword",
            "in": "query",
            "description": "LIKE users.name OR users.contact",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Candidate list (paginated envelope). Name/email masked (e.g. A***ce / a***@***.com)."
          },
          "400": {
            "description": "Invalid page or pageSize"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/candidates/{id}/remove-from-pool": {
      "post": {
        "summary": "Remove candidate from public pool",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Removed"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Candidate not found"
          }
        }
      }
    },
    "/v1/admin/audit": {
      "get": {
        "summary": "List unlock audit log entries",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "actor_user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "recommendation_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit list"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/action-history": {
      "get": {
        "summary": "List business action_history entries (admin-only; distinct from /audit which reads unlock_audit_log)",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "capability_name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "success",
                "error"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Action history list with pagination"
          },
          "400": {
            "description": "Invalid params (status not in [success,error] or limit out of range)"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/webhooks/dead-letter": {
      "get": {
        "summary": "List dead-letter webhook deliveries",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dead-letter list"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/webhooks/{id}/retry": {
      "post": {
        "summary": "Retry a dead-letter webhook",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Retry queued"
          },
          "400": {
            "description": "Invalid params"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Delivery not found"
          },
          "409": {
            "description": "Invalid state"
          }
        }
      }
    },
    "/v1/admin/rate-limit/buckets": {
      "get": {
        "summary": "List rate-limit buckets",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bucket list"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/rate-limit/users/{id}/clear": {
      "post": {
        "summary": "Clear rate-limit buckets for a user",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Buckets cleared"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/config": {
      "get": {
        "summary": "Read platform config (desensitization + commission)",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Config object"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/config/{key}": {
      "put": {
        "summary": "Update a config key (desensitization|commission)",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Saved"
          },
          "400": {
            "description": "Unknown key"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/placements": {
      "get": {
        "summary": "List placements",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending_payment",
                "paid",
                "cancelled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Placement list"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/placements/{id}/mark-paid": {
      "post": {
        "summary": "Mark placement as paid",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Marked paid"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Placement not found"
          }
        }
      }
    },
    "/v1/admin/placements/{id}/cancel": {
      "post": {
        "summary": "Cancel a placement",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Placement not found"
          },
          "409": {
            "description": "Invalid state"
          }
        }
      }
    },
    "/v1/admin/placements/summary": {
      "get": {
        "summary": "Placement summary stats",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Summary"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/admin-log": {
      "get": {
        "summary": "List admin action log entries",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Admin log list"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/admin/login-events": {
      "get": {
        "summary": "List admin login events (success + failure) — Sub-D1",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "parameters": [
          {
            "name": "admin_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "success",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            }
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Login events list (paginated envelope)"
          },
          "400": {
            "description": "Invalid page or pageSize"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/": {
      "get": {
        "summary": "Public landing page (HTML, no auth) — marketplace overview",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/skill.md": {
      "get": {
        "summary": "Redirects to /v1/skill.md",
        "security": [],
        "responses": {
          "301": {
            "description": "Moved"
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "summary": "Prometheus metrics (public)",
        "security": [],
        "responses": {
          "200": {
            "description": "text/plain Prometheus exposition"
          }
        }
      }
    },
    "/v1/metrics": {
      "get": {
        "summary": "Prometheus metrics (public, /v1 prefix)",
        "security": [],
        "responses": {
          "200": {
            "description": "text/plain Prometheus exposition"
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "summary": "This OpenAPI spec (public)",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.0 JSON"
          }
        }
      }
    },
    "/v1/skill.md": {
      "get": {
        "summary": "Agent skill documentation (public, Markdown)",
        "security": [],
        "responses": {
          "200": {
            "description": "text/markdown"
          }
        }
      }
    },
    "/v1/auth/register": {
      "post": {
        "summary": "Register a new user (candidate / headhunter / employer)",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_type",
                  "name"
                ],
                "properties": {
                  "user_type": {
                    "$ref": "#/components/schemas/UserType"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "contact": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "agent_endpoint": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registered",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "api_key": {
                              "type": "string"
                            },
                            "quota_per_day": {
                              "type": "integer"
                            },
                            "user_type": {
                              "$ref": "#/components/schemas/UserType"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParams"
          },
          "409": {
            "$ref": "#/components/responses/ContactTaken"
          }
        }
      }
    },
    "/v1/auth/rotate-key": {
      "post": {
        "summary": "Rotate the caller's API key. Old key is invalidated immediately (no grace period).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Rotated",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "new_api_key": {
                              "type": "string"
                            },
                            "new_prefix": {
                              "type": "string",
                              "minLength": 12,
                              "maxLength": 12
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/InsufficientQuota"
          }
        }
      }
    },
    "/v1/users/{id}/status": {
      "get": {
        "summary": "Get user status (quota / reputation / type)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/UserPublic"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/users/{id}/history": {
      "get": {
        "summary": "Get caller's own action history",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only return entries with created_at >= this ISO 8601 timestamp"
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ActionHistoryEntry"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidParams"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/candidate/opportunities": {
      "get": {
        "summary": "List recommendations for the candidate's anonymized profiles (candidate-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/InsufficientQuota"
          }
        }
      }
    },
    "/v1/candidate/access-log": {
      "get": {
        "summary": "List access-log entries that targeted the candidate (candidate-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/candidate/export-my-data": {
      "get": {
        "summary": "Export caller's own data (JSON download)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/candidate/delete-my-data": {
      "post": {
        "summary": "GDPR / data-subject erasure (candidate-only). Soft delete: PII wiped, anonymized stats preserved.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "anonymized_rows_preserved": {
                              "type": "integer"
                            },
                            "recommendations_withdrawn": {
                              "type": "integer"
                            },
                            "private_pii_rows_cleared": {
                              "type": "integer"
                            },
                            "deleted_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/InsufficientQuota"
          }
        }
      }
    },
    "/v1/candidate/recommendations/{id}/approve-unlock": {
      "post": {
        "summary": "Candidate approves employer unlock request (candidate-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Invalid state transition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      }
    },
    "/v1/candidate/recommendations/{id}/reject-unlock": {
      "post": {
        "summary": "Candidate rejects employer unlock request (candidate-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/employer/jobs": {
      "post": {
        "summary": "Create a job (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "salary_min": {
                    "type": "integer"
                  },
                  "salary_max": {
                    "type": "integer"
                  },
                  "industry": {
                    "type": "string"
                  },
                  "deadline": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent"
                    ]
                  },
                  "required_skills": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "get": {
        "summary": "List caller's jobs (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/employer/talent": {
      "get": {
        "summary": "Browse public-pool anonymized candidates (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/employer/placements": {
      "post": {
        "summary": "Create a placement after successful hire (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "get": {
        "summary": "List caller's placements (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/employer/recommendations/{id}/express-interest": {
      "post": {
        "summary": "Employer expresses interest in a recommendation (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Invalid state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      }
    },
    "/v1/employer/recommendations/{id}/unlock-contact": {
      "post": {
        "summary": "Employer unlocks candidate contact after candidate approval (employer-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/headhunter/candidates": {
      "post": {
        "summary": "Upload a candidate (headhunter-only; current_company REQUIRED, 1-200 chars)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "get": {
        "summary": "List caller's uploaded candidates (headhunter-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/headhunter/candidates/{id}/publish-to-pool": {
      "post": {
        "summary": "Publish candidate to public pool (headhunter-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/headhunter/recommendations": {
      "post": {
        "summary": "Recommend a candidate to a job (headhunter-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Duplicate recommendation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List caller's recommendations (headhunter-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/headhunter/recommendations/{id}/withdraw": {
      "post": {
        "summary": "Withdraw a recommendation (headhunter-only)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Invalid state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/industries": {
      "get": {
        "summary": "Industry reference (public, optional auth)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/title_levels": {
      "get": {
        "summary": "Title-level reference (public, optional auth)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/config/salary_bands": {
      "get": {
        "summary": "Salary-band reference (public, optional auth)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/market/leaderboard": {
      "get": {
        "summary": "Headhunter reputation leaderboard (public, optional auth)",
        "security": [],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/market/jobs": {
      "get": {
        "summary": "Public JD marketplace — all open jobs (v1.3 新增)",
        "security": [],
        "parameters": [
          {
            "name": "industry",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "完全匹配 jobs.industry（如 互联网）"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          }
        }
      }
    },
    "/v1/notifications/": {
      "get": {
        "summary": "List system notifications (in-site messages, 30-day TTL, polling). User-scoped: returns only caller's notifications.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Only return unread (read_at IS NULL)"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter by category (recommendation_accepted, unlock_granted, etc.)"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only return items with created_at > this ISO 8601 timestamp (for polling)"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Notification"
                              }
                            },
                            "unread_count": {
                              "type": "integer"
                            },
                            "has_more": {
                              "type": "boolean"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/notifications/{id}": {
      "get": {
        "summary": "Get single notification by id (user-scoped: 404 if not owned by caller)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Notification"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "summary": "Delete a single notification (user-scoped)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/notifications/{id}/read": {
      "post": {
        "summary": "Mark notification as read (idempotent — returns current read_at on repeat calls)",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "read_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/notifications/read-all": {
      "post": {
        "summary": "Mark all of caller's unread notifications as read",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "marked": {
                              "type": "integer",
                              "description": "Number of notifications marked as read"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/views/audit/{user_id}": {
      "post": {
        "summary": "Generate one-time view_url for the requesting user's own audit log (v1.1 引入). Only caller == user_id allowed.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "view_url": {
                              "type": "string",
                              "format": "uri"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/views/recommendation/{rec_id}": {
      "post": {
        "summary": "Generate one-time view_url for a recommendation (v1.1 引入). Caller must be the headhunter who created it or the employer on the target job.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ok"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "view_url": {
                              "type": "string",
                              "format": "uri"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/headhunter/jobs": {
      "post": {
        "summary": "Create a job on behalf of an employer (headhunter-only)",
        "description": "猎头为雇主建岗。job 入库后 employer_id=NULL, source_headhunter_id=caller, status=open,priority=normal。雇主事后通过 GET /v1/employer/pending-claims + POST /v1/employer/claim-jobs/{id} 认领,或 POST /v1/employer/reject-jobs/{id} 拒绝。扣 caller 的 create_job 配额(5)。",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "salary_min": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "salary_max": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "industry": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "deadline": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent"
                    ]
                  },
                  "required_skills": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 20
                  },
                  "created_for_employer_id": {
                    "type": "string",
                    "description": "Optional. If set, only this employer can claim. If null/omitted, any employer can claim."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "description": "Insufficient quota",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List jobs created by caller (headhunter-only)",
        "description": "返回 source_headhunter_id=caller 的所有 job(含未认领/已认领/已关闭)。",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/employer/pending-claims": {
      "get": {
        "summary": "List pending-claim jobs (employer-only)",
        "description": "返回 status=open AND employer_id IS NULL AND (created_for_employer_id=me OR created_for_employer_id IS NULL) 的 job。未认领的 job 在公开页隐藏,只有创建猎头和被指定的雇主(或任何 employer,当 created_for_employer_id=NULL)能看到。",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/employer/claim-jobs/{id}": {
      "post": {
        "summary": "Claim a headhunter-created job (employer-only)",
        "description": "认领成功后 job.employer_id=caller,公开页可见。Idempotent: 同一 employer 重复 claim 自己的 job 返回 200 no-op。已认领给别人的 job 返回 409 INVALID_STATE。无权认领(创建猎头指定了别的雇主)的 job 返回 403 FORBIDDEN。",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Invalid state (job already claimed, closed, or filled)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      }
    },
    "/v1/employer/reject-jobs/{id}": {
      "post": {
        "summary": "Reject a pending-claim job (employer-only)",
        "description": "拒绝后 job.status=closed,永久下线。雇主可以传 reason(可选, max 500 字符),记录到 action_history 审计日志。",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Invalid state (job already closed or filled)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Err"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/users/{id}": {
      "get": {
        "summary": "Get users",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/jobs/{id}": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/candidates/{id}": {
      "get": {
        "summary": "Get candidates",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/recommendations/{id}": {
      "get": {
        "summary": "Get recommendations",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/jobs": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/recommendations": {
      "get": {
        "summary": "Get recommendations",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/admin/timeline/{type}/{id}": {
      "get": {
        "summary": "Get timeline",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/auth/login": {
      "post": {
        "summary": "POST /v1/auth/login",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/auth/refresh": {
      "post": {
        "summary": "POST /v1/auth/refresh",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/auth/logout": {
      "post": {
        "summary": "POST /v1/auth/logout",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/auth/otp/request": {
      "post": {
        "summary": "Request request",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/auth/otp/verify": {
      "post": {
        "summary": "Verify verify",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/jobs/browse": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/jobs/recommended": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/jobs/{id}": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/jobs/{id}/apply": {
      "post": {
        "summary": "Apply apply",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/applications": {
      "get": {
        "summary": "Get applications",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/applications/{id}": {
      "get": {
        "summary": "Get applications",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/applications/{id}/respond": {
      "post": {
        "summary": "Respond respond",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/profile": {
      "get": {
        "summary": "Get profile",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "put": {
        "summary": "Update profile",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/profile/audit-log": {
      "get": {
        "summary": "Get audit-log",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/candidate-portal/messages": {
      "get": {
        "summary": "Get messages",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "post": {
        "summary": "POST /v1/candidate-portal/messages",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/config/rate-limits": {
      "get": {
        "summary": "Get rate-limits",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer-panel/dashboard": {
      "get": {
        "summary": "Get dashboard",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/pending-claims/{id}/claim": {
      "post": {
        "summary": "Claim claim",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/pending-claims/{id}/reject": {
      "post": {
        "summary": "Reject reject",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/jobs/{id}": {
      "get": {
        "summary": "Get jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "summary": "Update jobs",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/jobs/{id}/pause": {
      "post": {
        "summary": "Pause pause",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/jobs/{id}/resume": {
      "post": {
        "summary": "Resume resume",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/employer/jobs/{id}/close": {
      "post": {
        "summary": "Close close",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/dashboard": {
      "get": {
        "summary": "Get dashboard",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/tasks": {
      "get": {
        "summary": "Get tasks",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "post": {
        "summary": "POST /v1/headhunter-workspace/tasks",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/tasks/{id}": {
      "put": {
        "summary": "Update tasks",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "delete": {
        "summary": "Delete tasks",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/tasks/{id}/complete": {
      "post": {
        "summary": "Complete complete",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/tasks/{id}/reopen": {
      "post": {
        "summary": "Reopen reopen",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/kanban": {
      "get": {
        "summary": "Get kanban",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/kanban/move": {
      "post": {
        "summary": "Move move",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/kanban/add": {
      "post": {
        "summary": "Add add",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/kanban/remove": {
      "post": {
        "summary": "Remove remove",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter-workspace/stats": {
      "get": {
        "summary": "Get stats",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter/recommendations/pending-pickup": {
      "get": {
        "summary": "Get pending-pickup",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/headhunter/recommendations/{id}/pickup": {
      "post": {
        "summary": "Pickup pickup",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects": {
      "post": {
        "summary": "POST /v1/pm/projects",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "summary": "Get projects",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{id}": {
      "get": {
        "summary": "Get projects",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "summary": "Update projects",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "delete": {
        "summary": "Delete projects",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/positions": {
      "post": {
        "summary": "POST /v1/pm/projects/{projectId}/positions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "summary": "Get positions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/positions/stats": {
      "get": {
        "summary": "Get stats",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/positions/bulk": {
      "post": {
        "summary": "Bulk bulk",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/positions/{id}": {
      "get": {
        "summary": "Get positions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "summary": "Update positions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "delete": {
        "summary": "Delete positions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/decompose": {
      "post": {
        "summary": "Decompose decompose",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/decompose/{decompositionId}/commit": {
      "post": {
        "summary": "Commit commit",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/decompositions": {
      "get": {
        "summary": "Get decompositions",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/projects/{projectId}/plans": {
      "post": {
        "summary": "POST /v1/pm/projects/{projectId}/plans",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "summary": "Get plans",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/plans/{id}": {
      "get": {
        "summary": "Get plans",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "summary": "Update plans",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "delete": {
        "summary": "Delete plans",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/plans/{id}/select": {
      "post": {
        "summary": "Select select",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/positions/{id}/sandbox": {
      "get": {
        "summary": "Get sandbox",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/positions/{id}/matches": {
      "get": {
        "summary": "Get matches",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/positions/{id}/matches/recompute": {
      "post": {
        "summary": "Recompute recompute",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/snapshot": {
      "get": {
        "summary": "Get snapshot",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/notes/{candidate_user_id}": {
      "get": {
        "summary": "Get notes",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "put": {
        "summary": "Update notes",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/pm/notes": {
      "get": {
        "summary": "Get notes",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/v1/webhooks/qing3": {
      "post": {
        "summary": "POST /v1/webhooks/qing3",
        "responses": {
          "200": {
            "description": "ok"
          },
          "401": {
            "description": "UNAUTHORIZED"
          },
          "403": {
            "description": "FORBIDDEN"
          },
          "404": {
            "description": "NOT_FOUND"
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    }
  }
}
