{"openapi":"3.1.0","info":{"title":"Tick Up API","version":"0.1.0"},"paths":{"/api/v1/health":{"get":{"tags":["health"],"summary":"Health Check","description":"API health check.","operationId":"health_check_api_v1_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Check Api V1 Health Head"}}}}}},"head":{"tags":["health"],"summary":"Health Check","description":"API health check.","operationId":"health_check_api_v1_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Check Api V1 Health Head"}}}}}}},"/api/v1/audit/actions":{"get":{"tags":["audit"],"summary":"List Action Audit Log","description":"Admin-only: who performed which high-value action, from where.\n\nTenant-scoped, newest first. Filterable by actor, action, and date range.\nAnswers the \"who did this?\" question (Xenia incident 2026-07-14) in one\nquery instead of a multi-source investigation.","operationId":"list_action_audit_log_api_v1_audit_actions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by the acting user","title":"User Id"},"description":"Filter by the acting user"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by semantic action, e.g. job.close","title":"Action"},"description":"Filter by semantic action, e.g. job.close"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events at/after this time","title":"Date From"},"description":"Only events at/after this time"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events at/before this time","title":"Date To"},"description":"Only events at/before this time"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ActionAuditLogResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys":{"get":{"tags":["api-keys"],"summary":"List Api Keys","description":"All of the company's keys — active, expired and revoked — newest first.","operationId":"list_api_keys_api_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["api-keys"],"summary":"Create Api Key","description":"Create a read-only Data API key. The full key is in this response only.","operationId":"create_api_key_api_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/api-keys/{key_id}":{"delete":{"tags":["api-keys"],"summary":"Revoke Api Key","description":"Revoke a key immediately. Idempotent: revoking a revoked key is a no-op.","operationId":"revoke_api_key_api_v1_api_keys__key_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/candidates":{"get":{"tags":["data"],"summary":"List Candidates","description":"Candidate profiles, by `created_at`. Duplicate-flagged profiles are\nincluded (see `duplicate_of_id`); anonymized ones keep their row with PII\nalready erased.","operationId":"list_candidates_api_v1_data_candidates_get","security":[{"ApiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataCandidate_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/applications":{"get":{"tags":["data"],"summary":"List Applications","description":"One row per candidate × job, by entry date (`applied_date`, else\n`created_at`). Same rows the Reports screen counts.","operationId":"list_applications_api_v1_data_applications_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataApplication_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/stage-transitions":{"get":{"tags":["data"],"summary":"List Stage Transitions","description":"Every stage move / status change of those applications, by `changed_at`.","operationId":"list_stage_transitions_api_v1_data_stage_transitions_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataStageTransition_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/jobs":{"get":{"tags":["data"],"summary":"List Jobs","description":"Job postings with their pipeline stages, by `created_at`.","operationId":"list_jobs_api_v1_data_jobs_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataJob_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/interviews":{"get":{"tags":["data"],"summary":"List Interviews","description":"Interviews, by `scheduled_at` (future dates allowed via `to`).","operationId":"list_interviews_api_v1_data_interviews_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataInterview_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/evaluations":{"get":{"tags":["data"],"summary":"List Evaluations","description":"Scorecards, by `evaluated_at` (else `created_at`). Comments are not included.","operationId":"list_evaluations_api_v1_data_evaluations_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataEvaluation_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/offers":{"get":{"tags":["data"],"summary":"List Offers","description":"Offer letters — every version — by `created_at`.","operationId":"list_offers_api_v1_data_offers_get","security":[{"ApiKey":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Rows per page (max 100)","default":50,"title":"Page Size"},"description":"Rows per page (max 100)"},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped).","title":"From"},"description":"First day (YYYY-MM-DD, Vietnam time), on this table's time axis. Default and minimum: 18 months ago — older values are moved forward (meta.from_clamped)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last day (inclusive). Default: today.","title":"To"},"description":"Last day (inclusive). Default: today."},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync.","title":"Updated Since"},"description":"Only rows changed at/after this instant (ISO-8601; no timezone = UTC). For incremental sync."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports.","default":true,"title":"Include Demo"},"description":"Include onboarding demo rows (is_demo). Default true to match the Reports screen; set false for real reports."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataPage_DataOffer_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/metrics":{"get":{"tags":["data"],"summary":"Get Metrics","description":"The Reports screen's verified metrics for a period, computed exactly as\nthe screen does (same function). `period_start` shows the window actually\nused after the 18-month limit. Heavier than the tables: 20 calls/minute.","operationId":"get_metrics_api_v1_data_metrics_get","security":[{"ApiKey":[]}],"parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Period start (default/minimum: 18 months ago)","title":"From"},"description":"Period start (default/minimum: 18 months ago)"},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Period end, inclusive (default: today)","title":"To"},"description":"Period end, inclusive (default: today)"},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only rows of this job","title":"Job Id"},"description":"Only rows of this job"},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeatable: ?department=A&department=B","title":"Department"},"description":"Repeatable: ?department=A&department=B"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/data/catalog":{"get":{"tags":["data"],"summary":"Get Catalog","description":"Lookup lists to label the raw rows: pipeline templates + stages,\ncustom sources, rejection reasons, team members (no emails), departments.","operationId":"get_catalog_api_v1_data_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataCatalog"}}}}},"security":[{"ApiKey":[]}]}},"/api/v1/data/agent-guide":{"get":{"tags":["data"],"summary":"Get Agent Guide","description":"Starter guide for a coding agent (Markdown, Vietnamese): auth, data\nconventions, the data dictionary, metric definitions and sample questions.\nPublic — it contains no data.","operationId":"get_agent_guide_api_v1_data_agent_guide_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/auth/register":{"post":{"tags":["auth"],"summary":"Register","description":"Register a new account: creates a tenant and an admin user.\n\nHard gate (2026-07-28): no tokens are returned — the user must click the\nverification link emailed to them, and /verify-email performs the first\nlogin. See docs/plans/2026-07-28-email-verification-plan.md.","operationId":"register_api_v1_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__schemas__auth__MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["auth"],"summary":"Login","description":"Login with email and password.","operationId":"login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/google":{"post":{"tags":["auth"],"summary":"Google Auth","description":"Authenticate via Google. Creates account if first time.","operationId":"google_auth_api_v1_auth_google_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/refresh":{"post":{"tags":["auth"],"summary":"Refresh","description":"Rotate refresh token and get new access token.","operationId":"refresh_api_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/logout":{"post":{"tags":["auth"],"summary":"Logout","description":"Revoke the refresh token (logout).","operationId":"logout_api_v1_auth_logout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["auth"],"summary":"Get Me","description":"Get current user and tenant info.\n\n``tenant_id`` is the EFFECTIVE tenant (``deps.get_current_tenant_id``): the\nuser's own tenant normally, or — during a superadmin \"View as Tenant\"\nsession — the customer tenant being viewed, so /overview reflects whose data\nis on screen. ``user`` stays the real (superadmin) identity.","operationId":"get_me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/me/locale":{"patch":{"tags":["auth"],"summary":"Update Locale","description":"Update the current user's preferred locale (vi or en).","operationId":"update_locale_api_v1_auth_me_locale_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLocaleRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/me/signature":{"patch":{"tags":["auth"],"summary":"Update Signature","description":"Set or clear the current user's email signature.\n\nThe signature is appended (as HTML) to outbound emails this user sends or\ntriggers via stage changes — only when `auto_append_signature` is true.\nPass null/empty signature to clear.","operationId":"update_signature_api_v1_auth_me_signature_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSignatureRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/me/profile":{"patch":{"tags":["auth"],"summary":"Update Profile","description":"Update the current user's profile: full name, job title, avatar.\n\nReplaces all three from the profile page's current state (the frontend sends\nall three on save). ``avatar_url`` must be one of:\n  - ``null`` (clear → initials fallback),\n  - a Tick Up preset path (``/avatars/…``), or\n  - the tenant's own ``logo_url``.\nAny other value is rejected (422) to block off-domain/tracking image URLs.","operationId":"update_profile_api_v1_auth_me_profile_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/invite":{"post":{"tags":["auth"],"summary":"Create Invite","description":"Create an invite token (admin only).","operationId":"create_invite_api_v1_auth_invite_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/invite/lookup":{"post":{"tags":["auth"],"summary":"Lookup Invite","description":"Return the invited email + company for a valid invite token.\n\nThe accept-invite page calls this to SHOW the invitee which email their new\naccount will use. Without it the form has no email field at all, so people\ntyped their own email into the Full Name box and locked themselves out\n(incident 2026-06-23). Does NOT consume the token. 400 if the token is\ninvalid, expired, or already used (mirrors register's validation).\n\nToken is sent in the body (not the URL) so it never lands in access logs.","operationId":"lookup_invite_api_v1_auth_invite_lookup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/invite/register":{"post":{"tags":["auth"],"summary":"Register With Invite","description":"Register a new user via an invite token.","operationId":"register_with_invite_api_v1_auth_invite_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteRegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/forgot-password":{"post":{"tags":["auth"],"summary":"Forgot Password","description":"Request a password reset email.\n\nAlways returns 200 regardless of whether the email exists (prevents enumeration).","operationId":"forgot_password_api_v1_auth_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__schemas__auth__MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/reset-password":{"post":{"tags":["auth"],"summary":"Reset Password","description":"Reset password using a valid reset token.","operationId":"reset_password_api_v1_auth_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__schemas__auth__MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/verify-email":{"post":{"tags":["auth"],"summary":"Verify Email","description":"Verify a signup email token and log the user in.\n\nThe verify click replaces the first login (hard gate, 2026-07-28), so this\nmirrors /login: last_login_at + best-effort demo seed + token issuance.","operationId":"verify_email_api_v1_auth_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/resend-verification":{"post":{"tags":["auth"],"summary":"Resend Verification","description":"Resend the signup verification email.\n\nAlways returns 200 regardless of whether the email exists (prevents\nenumeration, mirrors /forgot-password).","operationId":"resend_verification_api_v1_auth_resend_verification_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendVerificationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__schemas__auth__MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/tenant-code":{"get":{"tags":["company-pages"],"summary":"Get Tenant Code","description":"Get the current tenant's company code for building public URLs.","operationId":"get_tenant_code_api_v1_company_pages_tenant_code_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-pages":{"get":{"tags":["company-pages"],"summary":"List Company Pages","description":"List all company pages for the current tenant.\nSupports pagination and status filtering.","operationId":"list_company_pages_api_v1_company_pages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"status_filter","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/PageStatus"},{"type":"null"}],"title":"Status Filter"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CompanyPageListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["company-pages"],"summary":"Create Company Page","description":"Create a new company page.\nAutomatically generates a page code with retry for race conditions.\n\nAdmin-only: career-page design/branding is a tenant-level resource. Every\nother write on this resource (update/content/publish/delete/subdomain)\nalready requires AdminUser — create was the one inconsistent gap that let a\nmember spawn a page (RBAC v2.2).","operationId":"create_company_page_api_v1_company_pages_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/assets/upload":{"post":{"tags":["company-pages"],"summary":"Upload Asset","description":"Upload an image asset.","operationId":"upload_asset_api_v1_company_pages_assets_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_asset_api_v1_company_pages_assets_upload_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-pages/assets":{"get":{"tags":["company-pages"],"summary":"List Assets","description":"List all assets for the tenant, optionally filtered by page.","operationId":"list_assets_api_v1_company_pages_assets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Page Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponse"},"title":"Response List Assets Api V1 Company Pages Assets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/assets/{asset_id}":{"delete":{"tags":["company-pages"],"summary":"Delete Asset","description":"Soft delete an asset.","operationId":"delete_asset_api_v1_company_pages_assets__asset_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/subdomain":{"put":{"tags":["company-pages"],"summary":"Set Page Subdomain","description":"Set or update the subdomain for a specific page.","operationId":"set_page_subdomain_api_v1_company_pages__page_id__subdomain_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubdomainUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}":{"get":{"tags":["company-pages"],"summary":"Get Company Page","description":"Get a specific company page by ID.","operationId":"get_company_page_api_v1_company_pages__page_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["company-pages"],"summary":"Update Company Page","description":"Update a company page.","operationId":"update_company_page_api_v1_company_pages__page_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["company-pages"],"summary":"Delete Company Page","description":"Soft delete a company page.","operationId":"delete_company_page_api_v1_company_pages__page_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/content":{"put":{"tags":["company-pages"],"summary":"Update Company Page Content","description":"Auto-save endpoint for updating page content only.\nUsed by the editor for real-time saving.","operationId":"update_company_page_content_api_v1_company_pages__page_id__content_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageContentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/publish":{"post":{"tags":["company-pages"],"summary":"Publish Company Page","description":"Publish a company page.\nCreates a version snapshot and sets status to published.","operationId":"publish_company_page_api_v1_company_pages__page_id__publish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPagePublish"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/unpublish":{"post":{"tags":["company-pages"],"summary":"Unpublish Company Page","description":"Unpublish a company page (set back to draft).","operationId":"unpublish_company_page_api_v1_company_pages__page_id__unpublish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/versions":{"get":{"tags":["company-pages"],"summary":"List Page Versions","description":"List versions of a company page (newest first, capped).","operationId":"list_page_versions_api_v1_company_pages__page_id__versions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PageVersionResponse"},"title":"Response List Page Versions Api V1 Company Pages  Page Id  Versions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-pages/{page_id}/restore/{version_id}":{"post":{"tags":["company-pages"],"summary":"Restore Page Version","description":"Restore a page to a previous version.","operationId":"restore_page_version_api_v1_company_pages__page_id__restore__version_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Page Id"}},{"name":"version_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Version Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs":{"get":{"tags":["jobs"],"summary":"List Jobs","description":"List all jobs for the current tenant.","operationId":"list_jobs_api_v1_jobs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"status_filter","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/JobStatus"},{"type":"null"}],"title":"Status Filter"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_JobListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["jobs"],"summary":"Create Job","description":"Create a new job listing.","operationId":"create_job_api_v1_jobs_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/suggestions":{"get":{"tags":["jobs"],"summary":"Get Job Suggestions","description":"Get distinct job titles and departments for autocomplete suggestions.","operationId":"get_job_suggestions_api_v1_jobs_suggestions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobFieldSuggestionsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/jobs/parse-url":{"post":{"tags":["jobs"],"summary":"Parse Job Url","description":"Enqueue a JD URL parse. Returns a job_id to poll via GET /jobs/parse/{id}.","operationId":"parse_job_url_api_v1_jobs_parse_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseUrlRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobParseEnqueueResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/jobs/parse-file":{"post":{"tags":["jobs"],"summary":"Parse Job File","description":"Enqueue a JD file parse (PDF or DOCX).","operationId":"parse_job_file_api_v1_jobs_parse_file_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_job_file_api_v1_jobs_parse_file_post"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobParseEnqueueResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/jobs/parse-text":{"post":{"tags":["jobs"],"summary":"Parse Job Text","description":"Enqueue a JD parse from pasted text.","operationId":"parse_job_text_api_v1_jobs_parse_text_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseTextRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobParseEnqueueResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/jobs/parse/{job_id}":{"get":{"tags":["jobs"],"summary":"Get Jd Parse Status","description":"Poll for the result of an enqueued JD parse.\n\nFrontend hits this every 2s until status moves to `completed` or `failed`.\nTenant-scoped so users can't peek at other tenants' parses.","operationId":"get_jd_parse_status_api_v1_jobs_parse__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobParseStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/duplicate":{"post":{"tags":["jobs"],"summary":"Duplicate Job","description":"Duplicate a job listing. Copies all fields except status (set to draft), dates, and applications.","operationId":"duplicate_job_api_v1_jobs__job_id__duplicate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}":{"get":{"tags":["jobs"],"summary":"Get Job","description":"Get a specific job by ID.","operationId":"get_job_api_v1_jobs__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["jobs"],"summary":"Update Job","description":"Update a job listing. Use PATCH /{job_id}/status to change status.","operationId":"update_job_api_v1_jobs__job_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["jobs"],"summary":"Delete Job","description":"Soft delete a job listing. Owner (Admin/Leader, or the owning Member) only.","operationId":"delete_job_api_v1_jobs__job_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/JobDeleteRequest"},{"type":"null"}],"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/status":{"patch":{"tags":["jobs"],"summary":"Change Job Status","description":"Change a job's status with transition validation and auto-triggers.","operationId":"change_job_status_api_v1_jobs__job_id__status_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusChangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/delete-impact":{"get":{"tags":["jobs"],"summary":"Get Job Delete Impact","description":"Preview the recruitment impact of deleting a job listing.\n\nReturns counts of active applications, hired candidates, interviews, and\noffer-reached applications so the frontend dialog can surface an appropriate\nwarning and suggest 'Close' instead of 'Delete' for jobs with real activity.\nOwner (Admin/Leader, or the owning Member) only — same authz as DELETE.","operationId":"get_job_delete_impact_api_v1_jobs__job_id__delete_impact_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobDeleteImpact"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/applications":{"get":{"tags":["jobs"],"summary":"List Job Applications","description":"List all applications for a job with candidate info.","operationId":"list_job_applications_api_v1_jobs__job_id__applications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"stage_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Ids"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApplicationWithCandidateResponse"},"title":"Response List Job Applications Api V1 Jobs  Job Id  Applications Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/activity":{"get":{"tags":["jobs"],"summary":"Get Job Activity","description":"Get recent stage change activity for a job.","operationId":"get_job_activity_api_v1_jobs__job_id__activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StageHistoryResponse"},"title":"Response Get Job Activity Api V1 Jobs  Job Id  Activity Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/analytics":{"get":{"tags":["jobs"],"summary":"Get Job Analytics","description":"Get per-job analytics: conversions, time-in-stage, sources, trends, interviews.\n\nPR2 §4.2 (HR Q7): per-job analytics is owner-only — require_job_owner 404s an\nunknown/cross-tenant/deleted job and 403s a non-owner (Admin/Leader pass\ntenant-wide; a Member only on jobs they own). The gate already verifies\nexistence, so the separate get_job_or_404 is gone.","operationId":"get_job_analytics_api_v1_jobs__job_id__analytics_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/analytics/export":{"get":{"tags":["jobs"],"summary":"Export Job Analytics","description":"Export per-job analytics as Excel (.xlsx).\n\nSheets:\n  1. Summary — KPIs (applications, hires, time-to-hire, offer acceptance)\n  2. Analytics — stage conversions, time in stage, source effectiveness, interview insights\n  3. Applications — one row per application for this job (for custom pivots)\n  4. Stage Transitions — one row per stage/status change for this job\n\nPR2 §4.2: gated on analytics:read ownership (was \"export\"); the gate returns\nthe Job (existence already verified) so we skip a redundant get_job_or_404.","operationId":"export_job_analytics_api_v1_jobs__job_id__analytics_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"}},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/pipeline":{"get":{"tags":["pipeline"],"summary":"Get Job Pipeline","description":"Get all pipeline stages for a job, ordered by sort_order.","operationId":"get_job_pipeline_api_v1_jobs__job_id__pipeline_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStageResponse"},"title":"Response Get Job Pipeline Api V1 Jobs  Job Id  Pipeline Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["pipeline"],"summary":"Replace Job Pipeline","description":"Bulk replace/update a job's pipeline stages.\n\nTwo modes, chosen by whether the payload carries stage ``id``s:\n\n* **Upsert (new clients)** — at least one incoming stage has an ``id``.\n  Matching ids are UPDATED in place, preserving each stage's UUID so every FK\n  (Application / Evaluation / StageHistory) survives a rename / reorder /\n  retype. Stages absent from the payload are deleted (same 409 +\n  ``stage_migrations`` contract for occupied stages); on delete-with-migration\n  both Application AND Evaluation are re-pointed to the target — no orphans.\n* **Legacy (old clients, no ids)** — delete-recreate fallback so a\n  not-yet-updated frontend keeps working. Remove once the FE always sends ids.","operationId":"replace_job_pipeline_api_v1_jobs__job_id__pipeline_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobPipelineUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStageResponse"},"title":"Response Replace Job Pipeline Api V1 Jobs  Job Id  Pipeline Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/pipeline/stages":{"post":{"tags":["pipeline"],"summary":"Add Pipeline Stage","description":"Add a single stage to a job's pipeline.","operationId":"add_pipeline_stage_api_v1_jobs__job_id__pipeline_stages_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStageCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/pipeline/stages/{stage_id}":{"patch":{"tags":["pipeline"],"summary":"Update Pipeline Stage","description":"Update a single pipeline stage (rename, reorder, recolor).","operationId":"update_pipeline_stage_api_v1_jobs__job_id__pipeline_stages__stage_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"stage_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Stage Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStageUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["pipeline"],"summary":"Delete Pipeline Stage","description":"Delete a pipeline stage (owner only). Blocked if any applications are in this stage.","operationId":"delete_pipeline_stage_api_v1_jobs__job_id__pipeline_stages__stage_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"stage_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Stage Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/job-templates":{"get":{"tags":["job-templates"],"summary":"List Job Templates","description":"Lightweight list for the job-form dropdown (any member) + settings table.","operationId":"list_job_templates_api_v1_job_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/JobTemplateListItem"},"type":"array","title":"Response List Job Templates Api V1 Job Templates Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["job-templates"],"summary":"Create Job Template","operationId":"create_job_template_api_v1_job_templates_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/job-templates/{template_id}":{"get":{"tags":["job-templates"],"summary":"Get Job Template","description":"Full template (stages + defaults) — prefills the job form on select.","operationId":"get_job_template_api_v1_job_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["job-templates"],"summary":"Update Job Template","operationId":"update_job_template_api_v1_job_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["job-templates"],"summary":"Delete Job Template","operationId":"delete_job_template_api_v1_job_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/job-templates/{template_id}/set-default":{"post":{"tags":["job-templates"],"summary":"Set Default Job Template","operationId":"set_default_job_template_api_v1_job_templates__template_id__set_default_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/vocab/languages":{"get":{"tags":["candidates"],"summary":"List Language Vocab","description":"Canonical language names for the New/Edit Candidate combobox.\n\nFree-text entry caused inconsistent values (\"English\" vs \"english\" vs\n\"Tiếng Anh\") that broke language filters + reports. The FE prefills this\nlist; rare languages fall through to a client-side \"Add new\" path and are\npersisted as-typed.","operationId":"list_language_vocab_api_v1_candidates_vocab_languages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array","title":"Response List Language Vocab Api V1 Candidates Vocab Languages Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/candidates/check-duplicate":{"post":{"tags":["candidates"],"summary":"Check Duplicate","description":"Check if a candidate with the same email, phone, or name already exists.\n\nReturns duplicate matches so the frontend can warn the user before creating.","operationId":"check_duplicate_api_v1_candidates_check_duplicate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"phone","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},{"name":"full_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"}},{"name":"exclude_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Exclude this candidate ID (for updates)","title":"Exclude Id"},"description":"Exclude this candidate ID (for updates)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateCheckResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/merge-duplicate":{"post":{"tags":["candidates"],"summary":"Merge Duplicate Candidate","description":"Merge a duplicate candidate into its original (Đồng nhất).\n\nThe NEW candidate's CV + data is applied to the EXISTING candidate,\nold CV is archived to history, applications are moved, and the\nduplicate record is soft-deleted.","operationId":"merge_duplicate_candidate_api_v1_candidates__candidate_id__merge_duplicate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{source_id}/merge-into/{target_id}":{"post":{"tags":["candidates"],"summary":"Merge Into Candidate","description":"Merge `source` into `target` with an explicit target (no duplicate_of_id required).\n\nUsed by the Edit Candidate dialog when a user types an email that belongs to\nanother candidate and chooses \"this is the same person — merge\". Same merge\nsemantics as `/merge-duplicate`: source's apps/CV move to target, source is\nsoft-deleted.","operationId":"merge_into_candidate_api_v1_candidates__source_id__merge_into__target_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}},{"name":"target_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Target Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/dismiss-duplicate":{"post":{"tags":["candidates"],"summary":"Dismiss Duplicate Candidate","description":"Dismiss the duplicate flag — keep as a separate candidate (Tạo mới).","operationId":"dismiss_duplicate_candidate_api_v1_candidates__candidate_id__dismiss_duplicate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/departments":{"get":{"tags":["candidates"],"summary":"List Departments","description":"Return distinct department names from active jobs.","operationId":"list_departments_api_v1_candidates_departments_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array","title":"Response List Departments Api V1 Candidates Departments Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/candidates/filter-options":{"get":{"tags":["candidates"],"summary":"Get Candidate Filter Options","description":"Return distinct skills and locations for candidate filter dropdowns.","operationId":"get_candidate_filter_options_api_v1_candidates_filter_options_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/candidates/tags/suggestions":{"get":{"tags":["candidates"],"summary":"Get Tag Suggestions","description":"Tag autocomplete for the inline editor.\n\nReturns up to `limit` distinct tag values from this tenant's candidates\nwhose lowercased form contains `q`. Backed by the GIN\n`idx_candidates_tenant_tags_gin` index (migration 102) for sub-10ms\nlatency on tag pools <10k entries — no in-memory cache needed.\n\nEmpty `q` returns the most-used tags (rough proxy: distinct values\nfrom the first 500 non-null tag rows; sufficient for the dropdown).","operationId":"get_tag_suggestions_api_v1_candidates_tags_suggestions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100,"description":"Prefix to match (case-insensitive)","default":"","title":"Q"},"description":"Prefix to match (case-insensitive)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"},"title":"Response Get Tag Suggestions Api V1 Candidates Tags Suggestions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/access-log":{"get":{"tags":["candidates"],"summary":"List Candidate Access Log","description":"Admin-only: who accessed candidates they don't own (Visibility not Walls).\n\nTenant-scoped, newest first. Filterable by viewer, owner, access type, and\ndate range. Powers the \"who uses whose candidate assets\" monitoring view —\nnothing here is masked or blocked; this is the audit trail of the logging.","operationId":"list_candidate_access_log_api_v1_candidates_access_log_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"viewer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by the user who accessed","title":"Viewer Id"},"description":"Filter by the user who accessed"},{"name":"owner_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by the candidate's owner","title":"Owner Id"},"description":"Filter by the candidate's owner"},{"name":"access_type","in":"query","required":false,"schema":{"anyOf":[{"enum":["detail","cv","export"],"type":"string"},{"type":"null"}],"description":"Filter by access type: detail | cv | export","title":"Access Type"},"description":"Filter by access type: detail | cv | export"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events at/after this time","title":"Date From"},"description":"Only events at/after this time"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only events at/before this time","title":"Date To"},"description":"Only events at/before this time"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CandidateAccessLogResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates":{"get":{"tags":["candidates"],"summary":"List Candidates","description":"List all candidates for the current tenant with filters.\n\nIncludes latest application data (stage, job title, department, applied date)\nvia a row_number() window subquery on the applications table.","operationId":"list_candidates_api_v1_candidates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},{"name":"is_blacklisted","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Blacklisted"}},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"}},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"}},{"name":"created_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created From"}},{"name":"stale_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Filter candidates stuck in stage for N+ days","title":"Stale Days"},"description":"Filter candidates stuck in stage for N+ days"},{"name":"job_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by job status (e.g. open)","title":"Job Status"},"description":"Filter by job status (e.g. open)"},{"name":"per_application","in":"query","required":false,"schema":{"type":"boolean","description":"Show one row per application instead of one per candidate","default":false,"title":"Per Application"},"description":"Show one row per application instead of one per candidate"},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by gender (male, female, other)","title":"Gender"},"description":"Filter by gender (male, female, other)"},{"name":"min_experience","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Minimum years of experience","title":"Min Experience"},"description":"Minimum years of experience"},{"name":"max_experience","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Maximum years of experience","title":"Max Experience"},"description":"Maximum years of experience"},{"name":"salary_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Minimum expected salary (VND)","title":"Salary Min"},"description":"Minimum expected salary (VND)"},{"name":"salary_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Maximum expected salary (VND)","title":"Salary Max"},"description":"Maximum expected salary (VND)"},{"name":"degree","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by degree (searches cv_parsed_data.education[].degree). Canonical keys (vocational/college/bachelor/master/phd/certificate) expand to variant patterns; other values match as lowercase substring. Repeat the param for multi-value OR semantics.","title":"Degree"},"description":"Filter by degree (searches cv_parsed_data.education[].degree). Canonical keys (vocational/college/bachelor/master/phd/certificate) expand to variant patterns; other values match as lowercase substring. Repeat the param for multi-value OR semantics."},{"name":"has_management_experience","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter candidates flagged as having management experience. OR of: recruiter manual tick (candidates.has_management_experience), AI-parsed CV verdict (primary + history), keyword match on current_job_title.","title":"Has Management Experience"},"description":"Filter candidates flagged as having management experience. OR of: recruiter manual tick (candidates.has_management_experience), AI-parsed CV verdict (primary + history), keyword match on current_job_title."},{"name":"skills","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated skill names to filter by","title":"Skills"},"description":"Comma-separated skill names to filter by"},{"name":"skill_match_mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(and|or)$"},{"type":"null"}],"description":"Skill matching mode: 'and' (all skills) or 'or' (any skill). Default: and","title":"Skill Match Mode"},"description":"Skill matching mode: 'and' (all skills) or 'or' (any skill). Default: and"},{"name":"ex_company","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by previous company name (searches cv_parsed_data). Repeat the param for multi-value OR semantics (?ex_company=A&ex_company=B).","title":"Ex Company"},"description":"Filter by previous company name (searches cv_parsed_data). Repeat the param for multi-value OR semantics (?ex_company=A&ex_company=B)."},{"name":"previous_job_title","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by previous job title (searches cv_parsed_data). Repeat the param for multi-value OR semantics.","title":"Previous Job Title"},"description":"Filter by previous job title (searches cv_parsed_data). Repeat the param for multi-value OR semantics."},{"name":"institution","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by education institution name (searches cv_parsed_data.education[].institution_name). Repeat the param for multi-value OR semantics.","title":"Institution"},"description":"Filter by education institution name (searches cv_parsed_data.education[].institution_name). Repeat the param for multi-value OR semantics."},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by language (searches cv_parsed_data.languages[].language). Repeat the param for multi-value OR semantics.","title":"Language"},"description":"Filter by language (searches cv_parsed_data.languages[].language). Repeat the param for multi-value OR semantics."},{"name":"language_proficiency","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Minimum language proficiency level","title":"Language Proficiency"},"description":"Minimum language proficiency level"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"FTS prefix trên toàn bộ search_vector (tên, chức danh/công ty, tags/notes/skills, nội dung CV thô, email/SĐT/mã/địa điểm/học vấn)","title":"Keyword"},"description":"FTS prefix trên toàn bộ search_vector (tên, chức danh/công ty, tags/notes/skills, nội dung CV thô, email/SĐT/mã/địa điểm/học vấn)"},{"name":"needs_manual_review","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter candidates flagged as needing manual review","title":"Needs Manual Review"},"description":"Filter candidates flagged as needing manual review"},{"name":"batch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter candidates uploaded in a specific batch","title":"Batch Id"},"description":"Filter candidates uploaded in a specific batch"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CandidateListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["candidates"],"summary":"Create Candidate","description":"Create a new candidate.","operationId":"create_candidate_api_v1_candidates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/parse-cv":{"post":{"tags":["candidates"],"summary":"Parse Cv Preview","description":"Parse a CV file and return extracted data without saving anything.\n\nUses LLM extraction if configured, otherwise falls back to regex-only.\nBefore calling the LLM, does a quick regex email extraction to check for\nduplicates — returns early with duplicate info to save LLM tokens.","operationId":"parse_cv_preview_api_v1_candidates_parse_cv_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force_parse","in":"query","required":false,"schema":{"type":"boolean","description":"Skip duplicate check and parse anyway","default":false,"title":"Force Parse"},"description":"Skip duplicate check and parse anyway"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_parse_cv_preview_api_v1_candidates_parse_cv_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CvParseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/upload-cv":{"post":{"tags":["candidates"],"summary":"Upload Candidate Cv","description":"Upload a CV file for an existing candidate - stores file and parses text.\n\nUses LLM extraction if configured. Checks for email duplicates before LLM\nparsing to save tokens.\n\nTwo modes — auto-detected from candidate state at call time:\n\n1. **Initial upload** (``candidate.cv_file_url`` is empty): Add Candidate\n   flow, just-created candidate. Auto-fill only sets candidate fields when\n   they are currently empty — preserves anything the user typed in the\n   review form. No CV archive (there's no prior CV).\n2. **Replace** (``candidate.cv_file_url`` is set): user is replacing an\n   existing CV from the candidate detail page. Group 1 (CV-derived) fields\n   are overwritten when the new CV has a value; Group 2 (recruiter-owned:\n   tags, notes, star_rating, source, blacklist*, communication_channel,\n   …) are never touched. The current CV (file URL + parsed_data) is\n   archived to ``CandidateCvHistory`` before being overwritten. See\n   ``memory/project_cv_replace_contract.md`` for the full policy.\n\nWhen ``parsed_data`` is supplied the LLM call is skipped — the canonical\nupload reuses the preview's parse result. Eliminates the ~15-20s second\nLLM round-trip that the modal-review flow previously incurred.\n\nWhen ``force_update=True`` the cross-candidate dedup short-circuit is skipped\nso the upload always proceeds, even if the CV's email/phone matches another\nactive candidate in the tenant.","operationId":"upload_candidate_cv_api_v1_candidates__candidate_id__upload_cv_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"force_update","in":"query","required":false,"schema":{"type":"boolean","description":"Skip cross-candidate email/phone collision check. Set when caller has explicit user intent (e.g. user picked this candidate from a duplicate-detection dialog). Other safety checks still run.","default":false,"title":"Force Update"},"description":"Skip cross-candidate email/phone collision check. Set when caller has explicit user intent (e.g. user picked this candidate from a duplicate-detection dialog). Other safety checks still run."},{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"When set, attach the CV to this application (CV-per-application, phương án C) instead of overwriting the candidate's profile CV. The application must belong to this candidate. The profile CV (candidate.cv_*) is only set if the candidate has no CV yet.","title":"Application Id"},"description":"When set, attach the CV to this application (CV-per-application, phương án C) instead of overwriting the candidate's profile CV. The application must belong to this candidate. The profile CV (candidate.cv_*) is only set if the candidate has no CV yet."},{"name":"keep_separate","in":"query","required":false,"schema":{"type":"boolean","description":"GIỮ-RIÊNG (Nhịp 5, QĐ-0): khi ứng viên ĐÃ có CV và không gắn đơn, thêm CV mới vào hồ sơ (history, application_id NULL) thay vì ĐÈ CV chính. Bỏ qua khi có application_id (đã là đường gắn-đơn) hoặc khi ứng viên chưa có CV (CV đầu thành CV chính).","default":false,"title":"Keep Separate"},"description":"GIỮ-RIÊNG (Nhịp 5, QĐ-0): khi ứng viên ĐÃ có CV và không gắn đơn, thêm CV mới vào hồ sơ (history, application_id NULL) thay vì ĐÈ CV chính. Bỏ qua khi có application_id (đã là đường gắn-đơn) hoặc khi ứng viên chưa có CV (CV đầu thành CV chính)."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_candidate_cv_api_v1_candidates__candidate_id__upload_cv_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CvUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/batch-upload":{"post":{"tags":["candidates"],"summary":"Batch Upload Cvs","description":"Upload up to 10 CV files at once for background LLM parsing.\n\nFor each file: validate → create candidate row with placeholder full_name →\nupload to R2 → insert cv_parse_jobs row (status=pending). After commit, fire\nthe worker in the background. Returns a batch_id the client can poll.\n\nFiles are not parsed synchronously — call GET /batch-upload/{batch_id} to\ntrack progress. Candidates appear immediately with needs_manual_review=true.","operationId":"batch_upload_cvs_api_v1_candidates_batch_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_batch_upload_cvs_api_v1_candidates_batch_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/candidates/batch-upload/{batch_id}":{"get":{"tags":["candidates"],"summary":"Get Batch Upload Status","description":"Poll the status of a batch CV upload.\n\nReturns per-file status and a summary. Complete=true when every file has\nreached a terminal state (parsed, empty, or failed with retries exhausted).","operationId":"get_batch_upload_status_api_v1_candidates_batch_upload__batch_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Batch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchUploadStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/retry-parse-job":{"post":{"tags":["candidates"],"summary":"Retry Parse Job","description":"Reset the latest cv_parse_job for this candidate so the worker picks it up.\n\nUsed by the Retry button on the candidate detail banner for jobs that ended\nin ``failed`` (retries exhausted) or ``empty`` (LLM returned nothing usable).\nOnly those two terminal states are retryable — ``parsed`` jobs are already\nsuccessful, and ``pending``/``processing`` jobs are in-flight.","operationId":"retry_parse_job_api_v1_candidates__candidate_id__retry_parse_job_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/reparse-cv":{"post":{"tags":["candidates"],"summary":"Reparse Candidate Cv","description":"Re-parse an existing CV that was uploaded but never parsed (career-site\napplications, or a parse that previously hit quota).\n\nEnqueues a durable cv_parse_jobs row (manual origin: batch_id + application_id\nNULL) and returns immediately. cv_parse_worker downloads the CV, runs the LLM,\nand — because it's a queue row — retries on an LLM error / network blip instead\nof losing the parse. The frontend polls / reloads to see results.","operationId":"reparse_candidate_cv_api_v1_candidates__candidate_id__reparse_cv_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}":{"get":{"tags":["candidates"],"summary":"Get Candidate","description":"Get a specific candidate by ID.\n\nAnonymized candidates are returned with HTTP 200 + the placeholder\nname and `is_anonymized=true`. The frontend uses this signal to\nrender the read-only banner instead of the generic 404 page —\nfixes the \"Không tìm thấy ứng viên\" UX when clicking notifications\nthat point at an anonymized candidate.","operationId":"get_candidate_api_v1_candidates__candidate_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["candidates"],"summary":"Update Candidate","description":"Update a candidate.\n\nOptimistic concurrency control: callers SHOULD send the candidate's\ncurrent `updated_at` (ISO-8601) in the `If-Unmodified-Since` header.\nIf the candidate has been modified since that timestamp, the request\nis rejected with 409. Without the header (legacy callers, batch jobs)\nthe check is skipped and last-write-wins applies.","operationId":"update_candidate_api_v1_candidates__candidate_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"If-Unmodified-Since","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Unmodified-Since"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["candidates"],"summary":"Delete Candidate","description":"Soft delete a candidate.\n\nDEPRECATED — kept for backward compatibility while the frontend\nmigrates to POST /candidates/{id}/anonymize. New code MUST use\nthe anonymize endpoint, which strips PII (PDPD compliance) and\nenforces admin-only + typing-confirm + active-app guards.\n\nAdmin-only: destructive deletes follow the same gate as the\nanonymize/blacklist/merge endpoints (security hotfix 95cbdb98).\n\nSee docs/plans/candidate-lifecycle-redesign.md.","operationId":"delete_candidate_api_v1_candidates__candidate_id__delete","deprecated":true,"security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/cv-history":{"get":{"tags":["candidates"],"summary":"List Candidate Cv History","description":"Bộ CV đầy đủ của một ứng viên: CV chính (candidate.cv_*) ∪ candidate_cv_history (Nhịp 5, QĐ#1).\n\nDedup: nếu một dòng history trùng CV chính (so theo hash, fallback url) thì dòng đó được đánh\ndấu ``is_primary`` (dùng id của nó cho mọi thao tác) thay vì tạo mục CV-chính riêng — tránh\nhiển thị 1 CV hai lần. CV chính đứng đầu, CV phụ theo ``archived_at`` giảm dần. ``job_title``\nresolve từ ``job_id`` để hiển thị \"CV cho job X\". Quyền: chỉ cần đăng nhập (khớp upload-cv /\nset-primary — quản lý CV là thao tác vận hành thường ngày).","operationId":"list_candidate_cv_history_api_v1_candidates__candidate_id__cv_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'parsed' → kèm cv_parsed_data từng CV (WS8 tab đa-hồ-sơ). Mặc định KHÔNG trả để giữ payload nhẹ cho card Bộ CV.","title":"Include"},"description":"'parsed' → kèm cv_parsed_data từng CV (WS8 tab đa-hồ-sơ). Mặc định KHÔNG trả để giữ payload nhẹ cho card Bộ CV."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CvHistoryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/cv-history/{cv_history_id}/set-primary":{"post":{"tags":["candidates"],"summary":"Set Primary Cv Endpoint","description":"Đặt một CV trong lịch sử làm CV chính của hồ sơ ứng viên (phương án C, QĐ#1).\n\nCopy CV đã chọn vào ``candidate.cv_*`` — CV đại diện cho mọi luồng candidate-level\n(hiển thị mặc định, tìm kiếm, sourcing job mới, tải CV, resolver fallback). CV chính cũ\nđược archive vào history nếu chưa có (không mất CV). Re-index search tự động.\n\nQuyền: chỉ cần đăng nhập (khớp ``upload-cv``) — quản lý CV là thao tác vận hành thường ngày.\nMark điểm matching stale (như ``update_candidate``): matching HIỆN đọc CV chính\n(``calculate_match_llm``), nên đổi CV chính làm điểm cached cũ → ``is_valid=False``\n(non-destructive) để HR chấm lại. Nhịp 3 (matching per-application) sẽ thu hẹp scope.","operationId":"set_primary_cv_endpoint_api_v1_candidates__candidate_id__cv_history__cv_history_id__set_primary_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"cv_history_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cv History Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/cv-pending/{cv_history_id}/resolve":{"post":{"tags":["candidates"],"summary":"Resolve Pending Cv Endpoint","description":"HR quyết CV đang CHỜ ĐỐI CHIẾU (WS4/QĐ-F): Thay / Giữ cả hai / Bỏ qua.\n\n- ``replace``: dòng tier-1 cũ của đơn → orphan archive (vẫn trong Bộ CV, giữ vết\n  audit); CV chờ trở thành CV của đơn. KHÔNG invalidate điểm (D8b — row id của đơn\n  đổi nên banner provenance tự sáng); response ``offer_rescore=True`` để FE hỏi\n  \"chấm lại AI matching?\".\n- ``keep_both``: CV chờ thành CV phụ (giữ nhãn job, ``rebind_eligible=False`` — D6).\n- ``discard``: xóa dòng + file R2 best-effort + reindex search sạch dấu vết.\n\nQuyền: đăng nhập (khớp upload-cv/set-primary — vận hành thường ngày).","operationId":"resolve_pending_cv_endpoint_api_v1_candidates__candidate_id__cv_pending__cv_history_id__resolve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"cv_history_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cv History Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CvPendingResolveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CvPendingResolveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/cv-history/{cv_history_id}/reparse":{"post":{"tags":["candidates"],"summary":"Reparse Cv History Row","description":"Parse lại MỘT dòng CV cụ thể trong Bộ CV (WS8/D11) — kết quả ghi vào ĐÚNG dòng đó.\n\nTrước R3 chỉ có đường parse-lại CV CHÍNH (reparse-cv) — CV phụ parse-lỗi/chưa-từng-\nparse không có lối tự phục hồi nội dung (audit OV-8). Cơ chế: phiếu CvParseJob mang\n``target_history_id`` (D3), worker ghi theo PK + hash-predicate.","operationId":"reparse_cv_history_row_api_v1_candidates__candidate_id__cv_history__cv_history_id__reparse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"cv_history_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cv History Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/anonymize":{"post":{"tags":["candidates"],"summary":"Anonymize Candidate Endpoint","description":"Permanently anonymize a candidate's PII (PDPD compliance).\n\nGuards (defense-in-depth — UI also enforces):\n  1. Admin-only: caller must have role='admin'.\n  2. Typing-confirm: query param confirm_text must equal 'DELETE'.\n  3. No active application: candidate must not have an application\n     with status='active'.\n  4. Not hired: candidate must not have an application with\n     status='hired' (use restore + then anonymize if needed).\n  5. Not already anonymized.\n\nSide effects:\n  - PII columns nulled, full_name → '[Đã xóa] #shortid'\n  - CV files + attachments deleted from storage (best-effort)\n  - Notifications referencing this candidate updated to show\n    '[Đã xóa]' so the inbox stays coherent\n  - Audit log row inserted\n\nReturns the anonymized candidate (200) so the frontend can\nredirect / show a confirmation banner.","operationId":"anonymize_candidate_endpoint_api_v1_candidates__candidate_id__anonymize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"confirm_text","in":"query","required":true,"schema":{"type":"string","description":"Must equal 'DELETE' to confirm","title":"Confirm Text"},"description":"Must equal 'DELETE' to confirm"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/delete-preview":{"get":{"tags":["candidates"],"summary":"Get Candidate Delete Preview","description":"Preview what will be cascade-deleted when hard-deleting a candidate.\n\nReturns the count of applications and distinct jobs that will be removed.\nCall this before DELETE /candidates/{id}/permanent to show the user what\nthey are about to destroy.\n\nNote: counts ALL applications (incl. soft-deleted) because CASCADE fires\non every row regardless of is_deleted. Candidate lookup also skips the\nis_deleted guard so already-soft-deleted candidates can still be previewed.","operationId":"get_candidate_delete_preview_api_v1_candidates__candidate_id__delete_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateDeletePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/permanent":{"delete":{"tags":["candidates"],"summary":"Hard Delete Candidate","description":"Permanently hard-delete a candidate and ALL related data.\n\nThis action is IRREVERSIBLE. FK CASCADE handles deletion of applications,\nstage_history, offer_letters, email_logs, attachments, drip_enrollments,\nmatching_scores, and all other child records automatically.\n\nFlow:\n  1. Advisory lock (prevents concurrent delete race)\n  2. Verify candidate exists in this tenant\n  3. Explicit DELETE cv_upload_queue (intentional NO CASCADE)\n  4. Explicit DELETE matching_queue (in-flight worker safety)\n  5. Null-out notification metadata so bell links don't 404\n  6. Write audit log (survives — candidate_audit_log has no FK to candidates)\n  7. Hard DELETE candidate → CASCADE fires\n  8. Commit\n  9. Best-effort R2 cleanup after commit","operationId":"hard_delete_candidate_api_v1_candidates__candidate_id__permanent_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"confirm_text","in":"query","required":false,"schema":{"type":"string","description":"Phải là 'DELETE' để xác nhận","default":"","title":"Confirm Text"},"description":"Phải là 'DELETE' để xác nhận"},{"name":"delete_reason","in":"query","required":false,"schema":{"type":"string","description":"Lý do xóa","default":"nhập nhầm/sai sót","title":"Delete Reason"},"description":"Lý do xóa"},{"name":"gdpr_request_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Ngày ứng viên yêu cầu xóa (GDPR, ISO date YYYY-MM-DD)","title":"Gdpr Request Date"},"description":"Ngày ứng viên yêu cầu xóa (GDPR, ISO date YYYY-MM-DD)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/blacklist":{"post":{"tags":["candidates"],"summary":"Toggle Blacklist","description":"Toggle candidate blacklist status.","operationId":"toggle_blacklist_api_v1_candidates__candidate_id__blacklist_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlacklistRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/tags":{"put":{"tags":["candidates"],"summary":"Update Tags","description":"Update candidate tags.","operationId":"update_tags_api_v1_candidates__candidate_id__tags_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateTagsUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/applications":{"get":{"tags":["candidates"],"summary":"List Candidate Applications","description":"List all applications for a candidate with job info.","operationId":"list_candidate_applications_api_v1_candidates__candidate_id__applications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApplicationWithJobResponse"},"title":"Response List Candidate Applications Api V1 Candidates  Candidate Id  Applications Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/complete-history":{"get":{"tags":["candidates"],"summary":"Get Complete History","description":"Get the candidate's complete hiring journey story.\n\nReturns a chronological, stage-centric narrative for each job application,\nwith interviews and evaluations nested under their respective stages,\nplus candidate context (notes, talent pool, blacklist status).","operationId":"get_complete_history_api_v1_candidates__candidate_id__complete_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateJourneyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/attachments":{"post":{"tags":["candidate-attachments"],"summary":"Upload Attachment","description":"Upload a file attachment to a candidate profile.","operationId":"upload_attachment_api_v1_candidates__candidate_id__attachments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_attachment_api_v1_candidates__candidate_id__attachments_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateAttachmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["candidate-attachments"],"summary":"List Attachments","description":"List all attachments for a candidate.","operationId":"list_attachments_api_v1_candidates__candidate_id__attachments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CandidateAttachmentResponse"},"title":"Response List Attachments Api V1 Candidates  Candidate Id  Attachments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/attachments/{attachment_id}":{"patch":{"tags":["candidate-attachments"],"summary":"Update Attachment","description":"Update attachment metadata (label, type).","operationId":"update_attachment_api_v1_candidates__candidate_id__attachments__attachment_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Attachment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateAttachmentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateAttachmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["candidate-attachments"],"summary":"Delete Attachment","description":"Soft-delete an attachment.","operationId":"delete_attachment_api_v1_candidates__candidate_id__attachments__attachment_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Attachment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/links":{"post":{"tags":["candidate-attachments"],"summary":"Create Link","description":"Add an external link to a candidate profile.","operationId":"create_link_api_v1_candidates__candidate_id__links_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateLinkCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateLinkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["candidate-attachments"],"summary":"List Links","description":"List all links for a candidate.","operationId":"list_links_api_v1_candidates__candidate_id__links_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CandidateLinkResponse"},"title":"Response List Links Api V1 Candidates  Candidate Id  Links Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/links/{link_id}":{"patch":{"tags":["candidate-attachments"],"summary":"Update Link","description":"Update a link.","operationId":"update_link_api_v1_candidates__candidate_id__links__link_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"link_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Link Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateLinkUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandidateLinkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["candidate-attachments"],"summary":"Delete Link","description":"Soft-delete a link.","operationId":"delete_link_api_v1_candidates__candidate_id__links__link_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"link_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Link Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/review-notes":{"post":{"tags":["candidate-review-notes"],"summary":"Create Review Note","description":"Create a new HR review note for a candidate.","operationId":"create_review_note_api_v1_candidates__candidate_id__review_notes_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["candidate-review-notes"],"summary":"List Review Notes","description":"List HR review notes for a candidate (pinned first, then newest first).\n\nDual-view: with ``application_id`` → notes for that job plus candidate-general\nnotes (application_id IS NULL); without → all notes across every application.\n``is_pinned DESC`` floats the pinned note to the top (so it's always within\nthe first page — the rail preview and the feed both surface it) and mirrors\nthe ``candidate.notes`` cache ordering (pinned-or-latest).","operationId":"list_review_notes_api_v1_candidates__candidate_id__review_notes_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Application window: chỉ ghi chú của job này + ghi chú chung (NULL). Bỏ trống (Talent Pool): mọi ghi chú của ứng viên.","title":"Application Id"},"description":"Application window: chỉ ghi chú của job này + ghi chú chung (NULL). Bỏ trống (Talent Pool): mọi ghi chú của ứng viên."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/review-notes/{note_id}":{"patch":{"tags":["candidate-review-notes"],"summary":"Update Review Note","description":"Edit a review note. Author-only (QĐ-4). System notes are immutable (D-E22).","operationId":"update_review_note_api_v1_candidates__candidate_id__review_notes__note_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["candidate-review-notes"],"summary":"Delete Review Note","description":"Soft-delete a review note. Author OR admin (D-E19). Refreshes cache.","operationId":"delete_review_note_api_v1_candidates__candidate_id__review_notes__note_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/candidates/{candidate_id}/review-notes/{note_id}/pin":{"patch":{"tags":["candidate-review-notes"],"summary":"Pin Review Note","description":"Pin/unpin a review note as the candidate's representative note (surfaced in\nthe rail \"Ghi chú mới nhất\" instead of the latest). Author OR admin, mirroring\ndelete. One pin per candidate: pinning clears any sibling. Refreshes the\ncandidate.notes cache (now pinned-or-latest).","operationId":"pin_review_note_api_v1_candidates__candidate_id__review_notes__note_id__pin_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNotePinRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewNoteMutationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications":{"get":{"tags":["applications"],"summary":"List Applications","description":"List applications for the tenant with pagination and filters.","operationId":"list_applications_api_v1_applications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"status_filter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Filter"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"position","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Position"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},{"name":"hired_date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hired Date From"}},{"name":"hired_date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hired Date To"}},{"name":"rejected_date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejected Date From"}},{"name":"rejected_date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejected Date To"}},{"name":"applied_date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied Date From"}},{"name":"applied_date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied Date To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ApplicationWithCandidateResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["applications"],"summary":"Create Application","description":"Create an application (link a candidate to a job).\n\nSau khi tạo, fire email trigger theo `initial_stage` (giống change_stage):\nstage=sourced skip; stage=applied dùng rule `applied` trong Automation\nTrigger (KHÔNG dùng cho public form — luồng đó check\ncompany_pages.settings.applicationForm.autoConfirmEmail); các stage khác\ndùng rule tương ứng. Response merge `email_info` (email_trigger,\nemail_preview, ...) để FE mở EmailSendModal khi rule ở manual_confirm.","operationId":"create_application_api_v1_applications_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/new-count":{"get":{"tags":["applications"],"summary":"Get New Application Count","description":"Return count of applications with is_new=True (unread by recruiter).","operationId":"get_new_application_count_api_v1_applications_new_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/applications/mark-read":{"post":{"tags":["applications"],"summary":"Mark Applications Read","description":"Mark all new applications as read for the tenant.","operationId":"mark_applications_read_api_v1_applications_mark_read_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/applications/{application_id}/mark-read":{"post":{"tags":["applications"],"summary":"Mark Application Read","description":"Mark a single application as read.","operationId":"mark_application_read_api_v1_applications__application_id__mark_read_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/validate-move":{"post":{"tags":["applications"],"summary":"Validate Stage Move","description":"Validate a stage move without executing it. Returns confirmation requirements.","operationId":"validate_stage_move_api_v1_applications__application_id__validate_move_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StageChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StageMoveValidation"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/stage":{"patch":{"tags":["applications"],"summary":"Change Stage","description":"Change the pipeline stage of an application. May trigger email.\n\nSupports dual-write: accepts stage_id (new) or stage (legacy).\nIf stage_id is provided, it takes precedence.\n\nValidates direction (backward/skip-required needs confirmed=true).","operationId":"change_stage_api_v1_applications__application_id__stage_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StageChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/status":{"patch":{"tags":["applications"],"summary":"Change Status","description":"Change the status of an applicant (reject/hire/reopen).","operationId":"change_status_api_v1_applications__application_id__status_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/bulk-reject":{"post":{"tags":["applications"],"summary":"Bulk Reject","description":"Bulk reject multiple applications in a single transaction.","operationId":"bulk_reject_api_v1_applications_bulk_reject_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRejectRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRejectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/applications/rejection-reasons":{"get":{"tags":["applications"],"summary":"Get Rejection Reasons","description":"Get available rejection reason codes, optionally filtered by stage_type.\n\nPass `stage_type` (e.g., 'assessment', 'interview', 'offer') to filter\nreasons appropriate for that pipeline stage. If omitted, returns all reasons.","operationId":"get_rejection_reasons_api_v1_applications_rejection_reasons_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"stage_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Rejection Reasons Api V1 Applications Rejection Reasons Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/history":{"get":{"tags":["applications"],"summary":"Get Application History","description":"Get stage/status change history for an application.","operationId":"get_application_history_api_v1_applications__application_id__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StageHistoryResponse"},"title":"Response Get Application History Api V1 Applications  Application Id  History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}":{"patch":{"tags":["applications"],"summary":"Update Application","description":"Update application rating/recruiter.","operationId":"update_application_api_v1_applications__application_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/match-score":{"get":{"tags":["applications"],"summary":"Get Application Match Score","description":"Return the matching state + score (if available) for one application.","operationId":"get_application_match_score_api_v1_applications__application_id__match_score_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/retry-matching":{"post":{"tags":["applications"],"summary":"Retry Application Matching","description":"Manually retry matching for a `failed` application.\n\nRate-limited to 3 calls / 60s per application. Resets attempt counters,\nflips status → `analyzing`, and inserts (idempotent) a matching_queue row.","operationId":"retry_application_matching_api_v1_applications__application_id__retry_matching_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/run-matching":{"post":{"tags":["applications"],"summary":"Run Application Matching","description":"Manually trigger AI matching for a pending or stale application.\n\nAccepts: pending (never ran), done with stale score (job was edited), failed.\nRejects: analyzing (already running), no_cv, duplicate, quota_exceeded.\nRate-limited to 3 calls / 60s per application.","operationId":"run_application_matching_api_v1_applications__application_id__run_matching_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/remove":{"post":{"tags":["applications"],"summary":"Remove Application","description":"Hard-delete an application (irreversible remove from a job).\n\nThe candidate stays in the talent pool; the application row + its\npipeline data (stage_history, interviews, evaluations,\nmatching_queue) cascade-delete. email_log + talent_pool are preserved\nvia FK SET NULL. candidate_audit_log records a snapshot before delete\nso the \"ứng viên đã từng ứng tuyển job X\" trail is kept for PDPA.\n\nAdding the candidate back to the same job after this is treated as a\nfresh application (no restore path). Hired applications are blocked\nto avoid erasing a real hire from analytics.","operationId":"remove_application_api_v1_applications__application_id__remove_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveApplicationRequest"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/restore":{"post":{"tags":["applications"],"summary":"Restore Application","description":"Restore a rejected application back to active state.\n\nUsed when a recruiter changes their mind about a rejection (e.g. the\nchosen candidate fell through and they want to revisit a previously\nrejected applicant). Removed applications are hard-deleted and have\nno restore path — re-adding the candidate creates a fresh application.","operationId":"restore_application_api_v1_applications__application_id__restore_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreApplicationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/offers/prefill":{"get":{"tags":["offers"],"summary":"Get Prefill Data","description":"Data the FE uses to pre-fill the SendOfferDialog form.","operationId":"get_prefill_data_api_v1_applications__application_id__offers_prefill_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferPreFillData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/applications/{application_id}/offers":{"get":{"tags":["offers"],"summary":"List Offers","description":"All offer versions for an application, newest first.","operationId":"list_offers_api_v1_applications__application_id__offers_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__schemas__offer_letter__OfferListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["offers"],"summary":"Create Offer","description":"Create a new offer letter.\n\nReturns 409 OFFER_PENDING_EXISTS if an active pending offer already exists\non the application — the FE shows ``ResendWarningModal`` and lets the\nrecruiter withdraw + recreate in one combined flow. Returns 409\nOFFER_CROSS_JOB_WARN if the candidate already has an active offer on\nanother job (soft warning; retry with ``?force=true`` to override).","operationId":"create_offer_api_v1_applications__application_id__offers_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Bypass the Rào 5 cross-job warning (candidate has an active offer on another job). Any other 409 still blocks.","default":false,"title":"Force"},"description":"Bypass the Rào 5 cross-job warning (candidate has an active offer on another job). Any other 409 still blocks."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}":{"patch":{"tags":["offers"],"summary":"Patch Offer","description":"Edit a pending offer (recruiter adds missing details later).","operationId":"patch_offer_api_v1_offers__offer_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/accept":{"post":{"tags":["offers"],"summary":"Accept Offer","description":"Mark offer accepted on the candidate's behalf.\n\nDoes NOT flip application to hired — the FE receives a cascade suggestion\non the response and opens the CascadeConfirmDialog (S1) if HR wants to\nmove the application. See docs/plans/2026-07-17-offer-decouple-adaptive-popup.md.","operationId":"accept_offer_api_v1_offers__offer_id__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Match"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferAcceptRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/decline":{"post":{"tags":["offers"],"summary":"Decline Offer","description":"Mark offer declined.\n\nDoes NOT flip application to rejected — cascade is opt-in via the popup\n(S3). See docs/plans/2026-07-17-offer-decouple-adaptive-popup.md.","operationId":"decline_offer_api_v1_offers__offer_id__decline_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Match"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferDeclineRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/revise-result":{"post":{"tags":["offers"],"summary":"Revise Offer Result","description":"Log or re-log the candidate's response to an offer.\n\nUnlike /accept and /decline, this accepts ``accepted ↔ declined`` flips so\nHR can correct a logged result. Valid for both ``external`` and ``app``\noffers (Track B, 2026-07-18) — ``response_date`` is optional; when omitted\nthe existing ``responded_at`` is preserved.","operationId":"revise_offer_result_api_v1_offers__offer_id__revise_result_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Match"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferReviseResultRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/cancel":{"post":{"tags":["offers"],"summary":"Cancel Offer","description":"Company-side cancellation.\n\nDoes NOT flip application to rejected — cascade is opt-in via the popup\n(S4/S5). See docs/plans/2026-07-17-offer-decouple-adaptive-popup.md.","operationId":"cancel_offer_api_v1_offers__offer_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Match"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/withdraw":{"post":{"tags":["offers"],"summary":"Withdraw Offer","description":"Retract a pending offer to compose a new version — resend flow.\n\nSemantically distinct from `/cancel`: withdraw leaves the application at\nthe Offer stage with active status so the recruiter can immediately send\na revised offer. `/cancel` is company-side rejection and cascades the\napplication to Rejected. Wired to FE `ResendWarningModal`, which handles\nthe \"pending offer exists → withdraw + compose new\" branch of a 409\nOFFER_PENDING_EXISTS. Do NOT use this for company-side rejection —\nthat's `/cancel`.","operationId":"withdraw_offer_api_v1_offers__offer_id__withdraw_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferWithdrawRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferLetterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/postpone":{"post":{"tags":["offers"],"summary":"Postpone Start Date","description":"Push the offer's start_date to a later date + append a history row.\n\nOnboarding Status Modal option (spec session 2026-07-25). No limit on\npostpone count — HR keeps postponing until the candidate confirms Joined\n(`change_status(hired)`) or Cancel onboarding (`change_status(rejected)`).","operationId":"postpone_start_date_api_v1_offers__offer_id__postpone_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferPostponeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferStartDateChangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/postpone-history":{"get":{"tags":["offers"],"summary":"Get Postpone History","description":"List past start_date changes for an offer, newest first.","operationId":"get_postpone_history_api_v1_offers__offer_id__postpone_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferPostponeHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/attachments":{"get":{"tags":["offers"],"summary":"List Attachments","description":"List attachments on an offer (non-deleted, newest first).","operationId":"list_attachments_api_v1_offers__offer_id__attachments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferAttachmentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["offers"],"summary":"Upload Attachment","description":"Upload a PDF/Word evidence file to an offer. Max 5 MB, 3 files/offer.","operationId":"upload_attachment_api_v1_offers__offer_id__attachments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_attachment_api_v1_offers__offer_id__attachments_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferAttachmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/offers/{offer_id}/attachments/{attachment_id}":{"delete":{"tags":["offers"],"summary":"Delete Attachment","description":"Soft-delete an attachment. FE gates with a 2-step confirm dialog.","operationId":"delete_attachment_api_v1_offers__offer_id__attachments__attachment_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Offer Id"}},{"name":"attachment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Attachment Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tenants/me":{"get":{"tags":["tenants"],"summary":"Get Current Tenant","description":"Get current tenant info.","operationId":"get_current_tenant_api_v1_tenants_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInfoResponse"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["tenants"],"summary":"Delete Current Workspace","description":"Permanently delete the current admin's workspace (tenant + ALL data).\n\nSelf-service \"I signed up by mistake\" escape hatch. Hard-deletes the tenant;\nthe 49 ``ON DELETE CASCADE`` FKs (including ``users``) take the rest with it,\nwhich naturally frees the admin's email for a fresh signup/invite — no\nuniqueness rewrite, no migration.\n\nGuards (all enforced before any row is touched):\n  1. Confirm: ``confirm_text`` must equal the tenant's ``company_name``.\n  2. Sole-member: the tenant must contain exactly ONE user (this admin). If\n     any other member exists, refuse — the admin must remove them first. This\n     is the safest possible gate: a multi-person workspace can never be wiped\n     by a single actor.\n\nSix tables reference ``tenants`` with ``ON DELETE NO ACTION`` and would block\nthe cascade, so their rows are deleted first inside the same transaction:\n``cv_upload_queue``, ``matching_queue``, ``qc_issues``, ``usage_events``\n(all keyed by ``tenant_id``), and ``referrals`` (keyed by EITHER\n``referrer_tenant_id`` OR ``referred_tenant_id``). ``parse_attempts`` is\n``SET NULL`` and clears itself.\n\nAfter deletion the actor's user row is gone, so their access token fails the\n``get_current_user`` lookup on the next request (effectively logged out).","operationId":"delete_current_workspace_api_v1_tenants_me_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteWorkspaceRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tenants/me/logo":{"post":{"tags":["tenants"],"summary":"Upload Tenant Logo","description":"Upload (or replace) the tenant's company logo.\n\nStored in shared object storage under\n``{tenant_id}/tenant/logo_{timestamp}.{ext}``. The previous logo file is\nNOT cleaned up here (cheap on R2; cron-cleanable later if needed) —\noverwriting the URL on ``tenants.logo_url`` is what matters for callers.\n\nUsed by the SendOfferDialog \"Hiển thị logo công ty\" toggle, the career\npages, and the social-card export. Admin-only — tenant-level branding\nisn't something an individual recruiter should change.","operationId":"upload_tenant_logo_api_v1_tenants_me_logo_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_tenant_logo_api_v1_tenants_me_logo_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["tenants"],"summary":"Delete Tenant Logo","description":"Remove the tenant's company logo (sets ``logo_url`` to NULL).\n\nThe R2 object is NOT deleted (cheap, and may be linked from cached\nCloudflare worker bundles or old offer-letter snapshots — orphan\nartefacts are fine, dangling references are not).","operationId":"delete_tenant_logo_api_v1_tenants_me_logo_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInfoResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tenants/me/name":{"patch":{"tags":["tenants"],"summary":"Update Tenant Name","description":"Rename the tenant (the company display name).\n\nAdmin-only. ``company_code`` is NOT regenerated — it is referenced by\nauto-generated entity codes and stays stable for the tenant's lifetime.\nThe new name flows everywhere ``company_name`` is read: sidebar account\nbox, career pages, candidate emails, offer letters, and the\ndelete-workspace confirm text.","operationId":"update_tenant_name_api_v1_tenants_me_name_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantNameUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tenants/subdomain":{"put":{"tags":["tenants"],"summary":"Update Subdomain","description":"Set or update the tenant's subdomain.","operationId":"update_subdomain_api_v1_tenants_subdomain_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubdomainUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tenants/users":{"get":{"tags":["tenants"],"summary":"List Tenant Users","description":"List users in the current tenant.\n\nDefaults to active members only (existing hiring-team pickers rely on this).\nPass ``include_inactive=true`` to also return deactivated members — the\nMembers settings page uses this to render an explicit active/locked status.","operationId":"list_tenant_users_api_v1_tenants_users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserListResponse"},"title":"Response List Tenant Users Api V1 Tenants Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tenants/role-capabilities":{"get":{"tags":["tenants"],"summary":"Get Role Capabilities Map","description":"Return the capability set of every system role (Admin/Leader/Member).\n\nAny authenticated tenant member can read this — it exposes only the static\nrole→capability design, no tenant data. The single source of truth is\n``app/services/permissions.ROLE_CAPABILITIES`` so the frontend comparison\ntable never drifts from what the backend actually enforces.","operationId":"get_role_capabilities_map_api_v1_tenants_role_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleCapabilitiesResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tenants/users/{user_id}/role":{"put":{"tags":["tenants"],"summary":"Update User Role","description":"Change a member's role (admin-only).\n\nOn success the target's ``permission_version`` is bumped and all of their\nrefresh tokens are revoked, so the role change takes effect immediately:\nin-flight access tokens fail the ``pv`` check on their next request, and the\nnext refresh is rejected — forcing a fresh login under the new role.\n\nGuards prevent an admin from locking themselves (or the tenant) out of the\nonly admin account.","operationId":"update_user_role_api_v1_tenants_users__user_id__role_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tenants/users/{user_id}":{"delete":{"tags":["tenants"],"summary":"Remove Member","description":"Hard-delete a teammate and transfer their owned data to the acting admin.\n\nAdmin-only. The user row is permanently removed; everything they own/authored\n(jobs, candidates, campaigns, drips, offers, interviews, company pages, ...) is\nreassigned to ``admin`` first so no operational data is lost. Past-action audit\ncolumns fall to ON DELETE SET NULL (history is not falsified); personal data\n(tokens, notifications, integrations) is dropped by CASCADE. The admin gets an\nin-app notification summarising the inheritance.\n\nFull design + blast-radius: ``docs/plans/member-deactivation-2026-06-23.md``.\n\nGuards (in order):\n  1. Self — an admin can't delete their own account.\n  2. Advisory lock — tenant-scoped, transaction-level. Serialises member\n     mutations so two admins can't concurrently delete each other and leave the\n     tenant with zero admins (safe on the PgBouncer pooler; not session-level).\n  3. Cross-tenant — target must belong to the admin's tenant (else 404).\n  4. Confirm — ``confirm_text`` must match the target's name or email.\n  5. Last-admin — can't delete the only remaining active admin.","operationId":"remove_member_api_v1_tenants_users__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMemberRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviews":{"post":{"tags":["interviews"],"summary":"Create Interview","description":"Schedule a new interview for an application.","operationId":"create_interview_api_v1_interviews_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["interviews"],"summary":"List Interviews","description":"List interviews, filtered by application_id or candidate_id.","operationId":"list_interviews_api_v1_interviews_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}},{"name":"candidate_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InterviewWithContextResponse"},"title":"Response List Interviews Api V1 Interviews Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviews/self-schedule":{"post":{"tags":["interviews"],"summary":"Create Self Schedule Interview","description":"Create an interview with self-scheduling -- recruiter provides slots, candidate picks.","operationId":"create_self_schedule_interview_api_v1_interviews_self_schedule_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewSelfScheduleCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/interviews/{interview_id}":{"get":{"tags":["interviews"],"summary":"Get Interview","description":"Get interview detail with candidate/job context.","operationId":"get_interview_api_v1_interviews__interview_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewWithContextResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["interviews"],"summary":"Update Interview","description":"Update interview scheduling details.","operationId":"update_interview_api_v1_interviews__interview_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["interviews"],"summary":"Cancel Interview","description":"Cancel an interview (sets status=cancelled).","operationId":"cancel_interview_api_v1_interviews__interview_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviews/{interview_id}/reschedule":{"post":{"tags":["interviews"],"summary":"Reschedule Interview","description":"Reschedule an interview: creates a new interview linked to the original, sets old to RESCHEDULED.","operationId":"reschedule_interview_api_v1_interviews__interview_id__reschedule_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewReschedule"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviews/check-conflicts":{"post":{"tags":["interviews"],"summary":"Check Conflicts","description":"Standalone conflict check for interviewer scheduling.","operationId":"check_conflicts_api_v1_interviews_check_conflicts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewConflictCheck"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InterviewConflict"},"type":"array","title":"Response Check Conflicts Api V1 Interviews Check Conflicts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/interviews/{interview_id}/feedback":{"patch":{"tags":["interviews"],"summary":"Submit Feedback","description":"Submit interview feedback (auto-sets status=completed).","operationId":"submit_feedback_api_v1_interviews__interview_id__feedback_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewFeedbackSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviews/{interview_id}/candidate-response":{"patch":{"tags":["interviews"],"summary":"Mark Candidate Response","description":"Recruiter manually marks candidate acceptance/decline (verbal confirmation etc.).","operationId":"mark_candidate_response_api_v1_interviews__interview_id__candidate_response_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interview_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interview Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewCandidateResponseMark"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evaluation-templates/":{"get":{"tags":["evaluation-templates"],"summary":"List Evaluation Templates","description":"List all evaluation templates for the tenant.","operationId":"list_evaluation_templates_api_v1_evaluation_templates__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EvaluationTemplateResponse"},"type":"array","title":"Response List Evaluation Templates Api V1 Evaluation Templates  Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["evaluation-templates"],"summary":"Create Evaluation Template","description":"Create a new evaluation template.","operationId":"create_evaluation_template_api_v1_evaluation_templates__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationTemplateCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/evaluation-templates/{template_id}":{"get":{"tags":["evaluation-templates"],"summary":"Get Evaluation Template","description":"Get a single evaluation template.","operationId":"get_evaluation_template_api_v1_evaluation_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["evaluation-templates"],"summary":"Update Evaluation Template","description":"Update an evaluation template.","operationId":"update_evaluation_template_api_v1_evaluation_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["evaluation-templates"],"summary":"Delete Evaluation Template","description":"Soft-delete an evaluation template.","operationId":"delete_evaluation_template_api_v1_evaluation_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evaluations/":{"get":{"tags":["evaluations"],"summary":"List Evaluations","description":"List evaluations, filtered by application and/or interview.","operationId":"list_evaluations_api_v1_evaluations__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}},{"name":"interview_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Interview Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EvaluationResponse"},"title":"Response List Evaluations Api V1 Evaluations  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["evaluations"],"summary":"Create Evaluation","description":"Create a new evaluation.\n\nPhase 3 (Assessment System redesign): only HM Review flows allowed.\n- source='hm_review': HM submits via token (public endpoint, this internal endpoint not used)\n- source='on_behalf': Recruiter records HM's verbal decision when HM didn't fill the form.\n  Requires comments (audit trail explaining why recruiter is submitting on HM's behalf).\n- source='manual' and others: deprecated, returns 403.","operationId":"create_evaluation_api_v1_evaluations__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evaluations/{evaluation_id}":{"put":{"tags":["evaluations"],"summary":"Update Evaluation","description":"Update an evaluation.","operationId":"update_evaluation_api_v1_evaluations__evaluation_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"evaluation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Evaluation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["evaluations"],"summary":"Delete Evaluation","description":"Soft-delete an evaluation.","operationId":"delete_evaluation_api_v1_evaluations__evaluation_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"evaluation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Evaluation Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evaluations/summary":{"get":{"tags":["evaluations"],"summary":"Get Evaluation Summary","description":"Get aggregated evaluation summary for an application.","operationId":"get_evaluation_summary_api_v1_evaluations_summary_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluationSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviewer-contacts":{"get":{"tags":["interviewer-contacts"],"summary":"List Contacts","description":"List all interviewer contacts for the tenant.","operationId":"list_contacts_api_v1_interviewer_contacts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InterviewerContactResponse"},"type":"array","title":"Response List Contacts Api V1 Interviewer Contacts Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["interviewer-contacts"],"summary":"Create Contact","description":"Create a new interviewer contact.","operationId":"create_contact_api_v1_interviewer_contacts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewerContactCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewerContactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/interviewer-contacts/search":{"get":{"tags":["interviewer-contacts"],"summary":"Search Contacts","description":"Search interviewer contacts by name or email prefix.","operationId":"search_contacts_api_v1_interviewer_contacts_search_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","minLength":0,"maxLength":200,"default":"","title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InterviewerContactResponse"},"title":"Response Search Contacts Api V1 Interviewer Contacts Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interviewer-contacts/{contact_id}":{"put":{"tags":["interviewer-contacts"],"summary":"Update Contact","description":"Update an interviewer contact.","operationId":"update_contact_api_v1_interviewer_contacts__contact_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewerContactUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewerContactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["interviewer-contacts"],"summary":"Delete Contact","description":"Soft-delete an interviewer contact.","operationId":"delete_contact_api_v1_interviewer_contacts__contact_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interview-templates":{"get":{"tags":["interview-templates"],"summary":"List Templates","description":"List all interview templates for the current tenant.","operationId":"list_templates_api_v1_interview_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InterviewTemplateResponse"},"type":"array","title":"Response List Templates Api V1 Interview Templates Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["interview-templates"],"summary":"Create Template","description":"Create a new interview template.","operationId":"create_template_api_v1_interview_templates_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTemplateCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/interview-templates/{template_id}":{"get":{"tags":["interview-templates"],"summary":"Get Template","description":"Get a specific interview template.","operationId":"get_template_api_v1_interview_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["interview-templates"],"summary":"Update Template","description":"Update an interview template.","operationId":"update_template_api_v1_interview_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterviewTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["interview-templates"],"summary":"Delete Template","description":"Soft-delete an interview template.","operationId":"delete_template_api_v1_interview_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/calendar/auth-url":{"get":{"tags":["calendar"],"summary":"Get Auth Url","description":"Get Google OAuth consent URL for Calendar access.","operationId":"get_auth_url_api_v1_calendar_auth_url_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUrlResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/callback":{"post":{"tags":["calendar"],"summary":"Handle Callback","description":"Exchange Google authorization code for tokens and store them.\n\nMutually exclusive with Outlook: connecting Google removes any stored\nOutlook token for this user.","operationId":"handle_callback_api_v1_calendar_callback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__endpoints__calendar__CallbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarConnectedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/status":{"get":{"tags":["calendar"],"summary":"Get Calendar Status","description":"Check if the current user has a working Google Calendar connection.","operationId":"get_calendar_status_api_v1_calendar_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/disconnect":{"delete":{"tags":["calendar"],"summary":"Disconnect Calendar","description":"Remove stored Google Calendar tokens for the current user.","operationId":"disconnect_calendar_api_v1_calendar_disconnect_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/microsoft/auth-url":{"get":{"tags":["calendar"],"summary":"Get Outlook Auth Url Endpoint","operationId":"get_outlook_auth_url_endpoint_api_v1_calendar_microsoft_auth_url_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUrlResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/microsoft/callback":{"post":{"tags":["calendar"],"summary":"Handle Outlook Callback","description":"Exchange Outlook authorization code and store the token.\n\nMutually exclusive with Google: connecting Outlook removes any stored\nGoogle Calendar token for this user.","operationId":"handle_outlook_callback_api_v1_calendar_microsoft_callback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__endpoints__calendar__CallbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutlookConnectedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/microsoft/status":{"get":{"tags":["calendar"],"summary":"Get Outlook Status","operationId":"get_outlook_status_api_v1_calendar_microsoft_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/microsoft/disconnect":{"delete":{"tags":["calendar"],"summary":"Disconnect Outlook","operationId":"disconnect_outlook_api_v1_calendar_microsoft_disconnect_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/status/all":{"get":{"tags":["calendar"],"summary":"Get Combined Status","description":"Return connection status for both providers so the FE can render\na two-provider UI in one round-trip.","operationId":"get_combined_status_api_v1_calendar_status_all_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CombinedStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/calendar/settings":{"get":{"tags":["calendar"],"summary":"Get Calendar Settings","operationId":"get_calendar_settings_api_v1_calendar_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["calendar"],"summary":"Update Calendar Settings","operationId":"update_calendar_settings_api_v1_calendar_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-groups":{"get":{"tags":["talent-groups"],"summary":"List Talent Groups","description":"List tenant talent groups with computed member counts (shared across team).","operationId":"list_talent_groups_api_v1_talent_groups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TalentGroupListResponse"},"type":"array","title":"Response List Talent Groups Api V1 Talent Groups Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["talent-groups"],"summary":"Create Talent Group","description":"Create a talent group, optionally seeding it with candidate_ids (snapshot).","operationId":"create_talent_group_api_v1_talent_groups_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-groups/by-candidate/{candidate_id}":{"get":{"tags":["talent-groups"],"summary":"Groups For Candidate","description":"Groups a candidate belongs to (for chips on the candidate screen).","operationId":"groups_for_candidate_api_v1_talent_groups_by_candidate__candidate_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CandidateTalentGroup"},"title":"Response Groups For Candidate Api V1 Talent Groups By Candidate  Candidate Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-groups/{group_id}":{"get":{"tags":["talent-groups"],"summary":"Get Talent Group","description":"Get a single talent group with computed count.","operationId":"get_talent_group_api_v1_talent_groups__group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["talent-groups"],"summary":"Update Talent Group","description":"Rename / edit a talent group (any tenant member).","operationId":"update_talent_group_api_v1_talent_groups__group_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["talent-groups"],"summary":"Delete Talent Group","description":"Soft-delete a talent group. GATE (eng-review A2): admin OR the creator only —\na destructive, no-undo action must not be doable by any teammate.","operationId":"delete_talent_group_api_v1_talent_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-groups/{group_id}/members":{"get":{"tags":["talent-groups"],"summary":"List Group Members","description":"List operationally-visible members (anonymized/deleted candidates hidden).","operationId":"list_group_members_api_v1_talent_groups__group_id__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":500,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TalentGroupMemberResponse"},"title":"Response List Group Members Api V1 Talent Groups  Group Id  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["talent-groups"],"summary":"Add Group Members","description":"Add candidates (incl. rejected) to a group. Tenant-checked + deduped.","operationId":"add_group_members_api_v1_talent_groups__group_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentGroupMemberAdd"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-groups/{group_id}/members/{candidate_id}":{"delete":{"tags":["talent-groups"],"summary":"Remove Group Member","description":"Remove a candidate from a group (any tenant member).","operationId":"remove_group_member_api_v1_talent_groups__group_id__members__candidate_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-pool":{"get":{"tags":["talent-pool"],"summary":"List Talent Pool","description":"Advanced candidate search across the entire talent pool.","operationId":"list_talent_pool_api_v1_talent_pool_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"skills","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated skills","title":"Skills"},"description":"Comma-separated skills"},{"name":"ex_company","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeat the param for multi-value (?ex_company=A&ex_company=B). OR semantics — candidate matches if ANY of their working_experience[].company_name substring-matches any of the supplied values. Preserves single-value backward compat (?ex_company=A). Values containing commas are safe here (unlike a CSV variant).","title":"Ex Company"},"description":"Repeat the param for multi-value (?ex_company=A&ex_company=B). OR semantics — candidate matches if ANY of their working_experience[].company_name substring-matches any of the supplied values. Preserves single-value backward compat (?ex_company=A). Values containing commas are safe here (unlike a CSV variant)."},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated locations. Multi-value matched with OR semantics across location_display / vn_province_code / country_code (same shape as tag / skills filters).","title":"Location"},"description":"Comma-separated locations. Multi-value matched with OR semantics across location_display / vn_province_code / country_code (same shape as tag / skills filters)."},{"name":"experience_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Experience Min"}},{"name":"experience_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Experience Max"}},{"name":"degree","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeat the param for multi-value. Canonical keys (vocational/college/bachelor/master/phd/certificate) expand to variant patterns via degree_normalization.expand_degree_query; other values match as lowercase substring. OR semantics on education[].degree.","title":"Degree"},"description":"Repeat the param for multi-value. Canonical keys (vocational/college/bachelor/master/phd/certificate) expand to variant patterns via degree_normalization.expand_degree_query; other values match as lowercase substring. OR semantics on education[].degree."},{"name":"institution","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeat the param for multi-value. OR semantics on education[].institution_name substring match.","title":"Institution"},"description":"Repeat the param for multi-value. OR semantics on education[].institution_name substring match."},{"name":"salary_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"}},{"name":"salary_max","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"}},{"name":"salary_currency","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"description":"ISO-4217 3-letter currency code (VND/USD/EUR/JPY/SGD). When set, only candidates whose salary_currency matches EXACTLY are eligible — NULL currency dropped (fix 2026-07-03: previous inclusive NULL fallback let VND ranges leak into USD queries).","title":"Salary Currency"},"description":"ISO-4217 3-letter currency code (VND/USD/EUR/JPY/SGD). When set, only candidates whose salary_currency matches EXACTLY are eligible — NULL currency dropped (fix 2026-07-03: previous inclusive NULL fallback let VND ranges leak into USD queries)."},{"name":"salary_period","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(monthly|yearly|hourly)$"},{"type":"null"}],"description":"Salary period. When set, only candidates with the same salary_period match — NULL period dropped (monthly vs yearly ranges differ ~12×). Fix 2026-07-03.","title":"Salary Period"},"description":"Salary period. When set, only candidates with the same salary_period match — NULL period dropped (monthly vs yearly ranges differ ~12×). Fix 2026-07-03."},{"name":"salary_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"description":"Salary type. When set, only candidates with the same salary_type match — NULL type dropped. Fix 2026-07-03.","title":"Salary Type"},"description":"Salary type. When set, only candidates with the same salary_type match — NULL type dropped. Fix 2026-07-03."},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated tags. Multiple values matched with OR semantics (Excel-filter style).","title":"Tag"},"description":"Comma-separated tags. Multiple values matched with OR semantics (Excel-filter style)."},{"name":"min_rating","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5,"minimum":1},{"type":"null"}],"title":"Min Rating"}},{"name":"has_applications","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Applications"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"DEPRECATED — use language_pair for per-language level pairing. Kept for backward compat: OR semantics over cv_parsed_data.languages[].language substring.","title":"Language"},"description":"DEPRECATED — use language_pair for per-language level pairing. Kept for backward compat: OR semantics over cv_parsed_data.languages[].language substring."},{"name":"language_proficiency","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"DEPRECATED — use language_pair. Kept for backward compat with global-level callers.","title":"Language Proficiency"},"description":"DEPRECATED — use language_pair. Kept for backward compat with global-level callers."},{"name":"language_pair","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeat the param for multi-value (?language_pair=English:Advanced&language_pair=Japanese:Native). Format 'lang:level' — level is optional (omit for 'any level'). Per-pair same-element constraint: the SAME cv_parsed_data.languages[] entry must satisfy both language name (substring) AND proficiency_level (>= specified). OR semantics across pairs. Fix 2026-07-03 — replaces the buggy independent-AND behaviour of language+language_proficiency.","title":"Language Pair"},"description":"Repeat the param for multi-value (?language_pair=English:Advanced&language_pair=Japanese:Native). Format 'lang:level' — level is optional (omit for 'any level'). Per-pair same-element constraint: the SAME cv_parsed_data.languages[] entry must satisfy both language name (substring) AND proficiency_level (>= specified). OR semantics across pairs. Fix 2026-07-03 — replaces the buggy independent-AND behaviour of language+language_proficiency."},{"name":"has_management_experience","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Management Experience"}},{"name":"skill_match_mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"and|or — default and","title":"Skill Match Mode"},"description":"and|or — default and"},{"name":"previous_job_title","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Repeat the param for multi-value. OR semantics on working_experience[].job_title substring match.","title":"Previous Job Title"},"description":"Repeat the param for multi-value. OR semantics on working_experience[].job_title substring match."},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"FTS prefix trên toàn bộ search_vector (tên, chức danh/công ty, tags/notes/skills, nội dung CV thô, email/SĐT/mã/địa điểm/học vấn)","title":"Keyword"},"description":"FTS prefix trên toàn bộ search_vector (tên, chức danh/công ty, tags/notes/skills, nội dung CV thô, email/SĐT/mã/địa điểm/học vấn)"},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"male|female|other","title":"Gender"},"description":"male|female|other"},{"name":"needs_manual_review","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter candidates flagged as needing manual review","title":"Needs Manual Review"},"description":"Filter candidates flagged as needing manual review"},{"name":"batch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter candidates uploaded in a specific batch","title":"Batch Id"},"description":"Filter candidates uploaded in a specific batch"},{"name":"group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter to candidates who belong to this Talent Group (person-level membership). operational_candidate_filter already hides anonymized/soft-deleted candidates, so no extra visibility wiring is needed (eng-review A1 read-time).","title":"Group Id"},"description":"Filter to candidates who belong to this Talent Group (person-level membership). operational_candidate_filter already hides anonymized/soft-deleted candidates, so no extra visibility wiring is needed (eng-review A1 read-time)."},{"name":"last_activity_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Activity From"}},{"name":"last_activity_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Activity To"}},{"name":"current_job_title","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on candidates.current_job_title (case-insensitive). Used by the Vị trí column filter.","title":"Current Job Title"},"description":"Substring match on candidates.current_job_title (case-insensitive). Used by the Vị trí column filter."},{"name":"latest_stage","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated stage names. Candidate matches if their latest application is in any of these stages. Used by the Giai đoạn gần nhất column filter.","title":"Latest Stage"},"description":"Comma-separated stage names. Candidate matches if their latest application is in any of these stages. Used by the Giai đoạn gần nhất column filter."},{"name":"applied_job_title","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Substring match on the title of any of the candidate's applications. Repeat the param for multi-value (OR semantics — candidate matches if any title substring matches). Used by the Vị trí ứng tuyển column filter and the multi-select picker in SelectCandidateForJobModal.","title":"Applied Job Title"},"description":"Substring match on the title of any of the candidate's applications. Repeat the param for multi-value (OR semantics — candidate matches if any title substring matches). Used by the Vị trí ứng tuyển column filter and the multi-select picker in SelectCandidateForJobModal."},{"name":"status_filter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"active|inactive|hired — filter by application activity status","title":"Status Filter"},"description":"active|inactive|hired — filter by application activity status"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","pattern":"^(created_at|full_name|updated_at|last_activity|total_experience_years|relevance)$","default":"last_activity","title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"desc","title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TalentPoolCandidateResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-pool/status-counts":{"get":{"tags":["talent-pool"],"summary":"Get Status Counts","description":"Get candidate counts per status tab (all, active, hired, inactive).\n\nUses priority: hired > active > inactive to avoid double-counting\ncandidates who have both active and hired applications.","operationId":"get_status_counts_api_v1_talent_pool_status_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-pool/stats":{"get":{"tags":["talent-pool"],"summary":"Get Stats","description":"Get summary counts for the talent pool header cards.\n\nAll four counts share a single LEFT JOIN base so they are computed\nagainst the same candidate set. Previously `with_applications` was\na separate query that didn't filter `Candidate.is_deleted`, which\ncould push `without_applications` negative. The unified shape makes\nthat bug architecturally impossible: every count is bounded by the\nsame WHERE on Candidate.","operationId":"get_stats_api_v1_talent_pool_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentPoolStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-pool/filter-options":{"get":{"tags":["talent-pool"],"summary":"Get Filter Options","description":"Get distinct values for filter dropdowns.","operationId":"get_filter_options_api_v1_talent_pool_filter_options_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TalentPoolFilterOptions"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-pool/stage-options":{"get":{"tags":["talent-pool"],"summary":"Get Stage Options","description":"Data-derived stage options for the \"Giai đoạn gần nhất\" column filter.\n\nReturns distinct latest-stage labels (tenant-customised names) that at least\none operational candidate is currently in — so the filter matches the column\nbadges and never offers a dead option. This is the SSOT consumed by all\ncross-job stage filters (Talent Pool now; Active Applications + Candidates in\nPR2 of feat/stage-filter-ssot).","operationId":"get_stage_options_api_v1_talent_pool_stage_options_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/StageOption"},"type":"array","title":"Response Get Stage Options Api V1 Talent Pool Stage Options Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-pool/suggest":{"get":{"tags":["talent-pool"],"summary":"Suggest Filter Values","description":"Autocomplete source for the FE MultiValueTypeahead component.\n\nReturns DISTINCT values from ``cv_parsed_data[array_key][].field`` ordered by\nfrequency (how many candidates have that value). History-aware: unions both\n``candidates.cv_parsed_data`` and ``candidate_cv_history.cv_parsed_data`` so a\ncompany/school that only exists on a candidate's older CV still shows up.\n\nResponse shape: ``{\"items\": [{\"value\": str, \"count\": int}, ...]}``. Substring\nmatch (per spec: substring, not prefix — user chose 2026-07-02) with LIMIT to\nbound latency; FE debounces 250ms.","operationId":"suggest_filter_values_api_v1_talent_pool_suggest_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"field","in":"query","required":true,"schema":{"type":"string","description":"One of: company | job_title | institution | language | degree","title":"Field"},"description":"One of: company | job_title | institution | language | degree"},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Substring to match (case-insensitive). Empty → return top-N by frequency.","default":"","title":"Q"},"description":"Substring to match (case-insensitive). Empty → return top-N by frequency."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":25,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/talent-pool/bulk-rating":{"post":{"tags":["talent-pool"],"summary":"Bulk Set Rating","description":"Bulk-set star_rating (1-5 or null to clear) for multiple candidates.","operationId":"bulk_set_rating_api_v1_talent_pool_bulk_rating_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkRatingRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/talent-pool/{candidate_id}/rating":{"patch":{"tags":["talent-pool"],"summary":"Set Rating","description":"Set or clear (null) the star rating for a candidate.","operationId":"set_rating_api_v1_talent_pool__candidate_id__rating_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingRequest"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/jobs/{job_id}/match":{"post":{"tags":["matching"],"summary":"Run Matching","description":"Run AI matching for selected candidates against a job.\n\nUses LLM-powered scoring with 3 criteria:\nHard Skills (60), Experience Relevance (25), Requirement Fit (15).\nEach evaluation follows the 3-step verification protocol.\n\nResults are cached — re-running for already-matched candidates returns cached scores.","operationId":"run_matching_api_v1_matching_jobs__job_id__match_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchBatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchBatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/jobs/{job_id}/candidates":{"get":{"tags":["matching"],"summary":"Get Matched Candidates","description":"Get previously matched candidates for a job (cached results).\n\nReturns only candidates that have been matched via POST /match.\nUses LLM-powered scoring: Hard Skills (60), Experience Relevance (25),\nRequirement Fit (15).","operationId":"get_matched_candidates_api_v1_matching_jobs__job_id__candidates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":0,"default":0,"title":"Min Score"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchedCandidatesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/jobs/{job_id}/export":{"get":{"tags":["matching"],"summary":"Export Matched Candidates Csv","description":"Export matched candidates for a job as CSV, honoring the min-score filter.","operationId":"export_matched_candidates_csv_api_v1_matching_jobs__job_id__export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":0,"description":"Only export matches at or above this score — mirrors the list's min-score filter so the CSV matches what's on screen.","default":0,"title":"Min Score"},"description":"Only export matches at or above this score — mirrors the list's min-score filter so the CSV matches what's on screen."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/scores/{score_id}/feedback":{"post":{"tags":["matching"],"summary":"Submit Feedback","description":"Submit HR feedback on a match result (good/bad).","operationId":"submit_feedback_api_v1_matching_scores__score_id__feedback_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"score_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Score Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchFeedbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/jobs/{job_id}/recalculate":{"post":{"tags":["matching"],"summary":"Recalculate Job Matches","description":"Invalidate cached scores for a job and immediately re-match all candidates.\n\nUse this after updating job requirements (required_skills, experience, etc.).\nThis invalidates all existing scores and re-runs AI matching in one step.","operationId":"recalculate_job_matches_api_v1_matching_jobs__job_id__recalculate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"language","in":"query","required":false,"schema":{"enum":["vi","en"],"type":"string","default":"vi","title":"Language"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchBatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/scores/{score_id}/comment":{"post":{"tags":["matching"],"summary":"Submit Comment","description":"Submit a structured comment on a matching argument.","operationId":"submit_comment_api_v1_matching_scores__score_id__comment_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"score_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Score Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchingFeedbackCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/analytics/summary":{"get":{"tags":["matching"],"summary":"Get Matching Analytics","description":"Get aggregated matching analytics for the tenant.","operationId":"get_matching_analytics_api_v1_matching_analytics_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/matching/candidates/{candidate_id}/matching-history":{"get":{"tags":["matching"],"summary":"Get Matching History","description":"Get full matching history for a candidate (valid + outdated scores).","operationId":"get_matching_history_api_v1_matching_candidates__candidate_id__matching_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":5,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/matching/scores/{score_id}/comments":{"get":{"tags":["matching"],"summary":"Get Comments","description":"Get all feedback comments for a matching score.","operationId":"get_comments_api_v1_matching_scores__score_id__comments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"score_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Score Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/variables":{"get":{"tags":["emails"],"summary":"List Supported Variables","description":"List every {{template_var}} the system supports, with per-context support metadata.\n\nOptional query param ``context`` filters to vars available in that flow.\nValid contexts: manual_with_app, manual_no_app, campaign, drip, birthday,\nauto_trigger, public_confirm. See `docs/email-variables.md` for the\nmatrix and `email_service.SUPPORTED_VARIABLES` for the canonical dict.\n\nNo auth required — the contract is public information, no secrets.\nFrontend pickers use this to surface context-appropriate variables and\ngrey out the ones the current flow can't resolve.","operationId":"list_supported_variables_api_v1_emails_variables_get","parameters":[{"name":"context","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/templates":{"get":{"tags":["emails"],"summary":"List Templates","description":"List all email templates for the tenant.\n\nSystem-seeded templates (``system_key IS NOT NULL``) have their\nname/subject/body swapped to the ``locale`` variant on the fly, so a\ntenant that switches UI to English immediately sees English templates\nwithout any migration. User-edited rows are unaffected. See\n``_apply_template_locale`` for the overlay logic.","operationId":"list_templates_api_v1_emails_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(vi|en)$","default":"vi","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplateResponse"},"title":"Response List Templates Api V1 Emails Templates Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["emails"],"summary":"Create Template","description":"Create a new email template.","operationId":"create_template_api_v1_emails_templates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/templates/{template_id}":{"get":{"tags":["emails"],"summary":"Get Template","description":"Get a single email template. See list_templates for locale behavior.","operationId":"get_template_api_v1_emails_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}},{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(vi|en)$","default":"vi","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["emails"],"summary":"Update Template","description":"Update an email template.","operationId":"update_template_api_v1_emails_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["emails"],"summary":"Delete Template","description":"Soft delete an email template.","operationId":"delete_template_api_v1_emails_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/templates/seed-defaults":{"post":{"tags":["emails"],"summary":"Seed Default Templates","description":"Seed default email templates + matching automation rules.\n\nIdempotent — skips stages that already have templates. Phase 2: every seeded\ntemplate that's active by default also gets a matching `EmailAutomationRule`\n(so a stage change fires the email out of the box). See the service\nfunction for the full contract.\n\n``locale`` (query, default ``\"vi\"``) picks the language of the seeded\ncontent. FE passes ``useLocale()``. Existing templates the tenant already\nhas are left alone regardless of locale — this only fills in stages the\ntenant doesn't have yet, so calling with a new locale is safe.","operationId":"seed_default_templates_api_v1_emails_templates_seed_defaults_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(vi|en)$","default":"vi","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplateResponse"},"title":"Response Seed Default Templates Api V1 Emails Templates Seed Defaults Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/automation-rules":{"get":{"tags":["emails"],"summary":"List Automation Rules","description":"List all automation rules for the tenant (any stage, any mode).\n\nEach row carries a `sent_count` = number of email_logs where template_id\nmatches AND status is a delivered/opened/clicked terminal state. Computed\nvia a correlated scalar subquery per row — fine at the scale of tens of\nrules per tenant; would need rework if a tenant grew to hundreds.\n\n``locale`` swaps the display name of system-seeded sample rules (and\ntheir linked template snapshot) — user-edited rows are unaffected.","operationId":"list_automation_rules_api_v1_emails_automation_rules_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"locale","in":"query","required":false,"schema":{"type":"string","pattern":"^(vi|en)$","default":"vi","title":"Locale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailAutomationRuleResponse"},"title":"Response List Automation Rules Api V1 Emails Automation Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["emails"],"summary":"Create Automation Rule","description":"Create a stage-trigger rule attaching a template to a stage.","operationId":"create_automation_rule_api_v1_emails_automation_rules_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAutomationRuleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAutomationRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/automation-rules/{rule_id}":{"put":{"tags":["emails"],"summary":"Update Automation Rule","description":"Patch a rule — template, send_mode, priority, is_active.","operationId":"update_automation_rule_api_v1_emails_automation_rules__rule_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAutomationRuleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailAutomationRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["emails"],"summary":"Delete Automation Rule","description":"Hard delete a rule (no soft-delete on rules — they're cheap config).","operationId":"delete_automation_rule_api_v1_emails_automation_rules__rule_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/automation-reminders":{"get":{"tags":["emails"],"summary":"Get Automation Reminders","operationId":"get_automation_reminders_api_v1_emails_automation_reminders_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRemindersResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["emails"],"summary":"Update Automation Reminders","description":"Patch tenant reminder toggles. Missing fields leave the flag untouched.\n\nRequires `settings:update` capability (Admin only). Non-admin members can\nread via GET but cannot toggle — the workspace-wide reminder config is a\nshared resource; letting any member flip it would create a coordination\nmess (10 admins already surface the \"who changed it?\" question).","operationId":"update_automation_reminders_api_v1_emails_automation_reminders_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRemindersUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRemindersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/emails/preview":{"post":{"tags":["emails"],"summary":"Preview Email","description":"Preview an email with template variables replaced.","operationId":"preview_email_api_v1_emails_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/emails/send":{"post":{"tags":["emails"],"summary":"Send Email Endpoint","description":"Send an email (or schedule for later) and create a log entry.","operationId":"send_email_endpoint_api_v1_emails_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/emails/scheduled":{"get":{"tags":["emails"],"summary":"List Scheduled Emails","description":"List pending scheduled emails for the tenant.","operationId":"list_scheduled_emails_api_v1_emails_scheduled_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ScheduledEmailResponse"},"type":"array","title":"Response List Scheduled Emails Api V1 Emails Scheduled Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/emails/scheduled/{log_id}":{"delete":{"tags":["emails"],"summary":"Cancel Scheduled Email","description":"Cancel a scheduled email.","operationId":"cancel_scheduled_email_api_v1_emails_scheduled__log_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/attachments/upload":{"post":{"tags":["emails"],"summary":"Upload Email Attachment","description":"Upload a file attachment for an outbound email. Max 5 MB.","operationId":"upload_email_attachment_api_v1_emails_attachments_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_email_attachment_api_v1_emails_attachments_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/emails/logs/candidate/{candidate_id}":{"get":{"tags":["emails"],"summary":"List Candidate Logs","description":"List email logs for a specific candidate.\n\nWhen application_id is provided, returns logs tied to that application\nPLUS logs with application_id IS NULL (emails sent without an application\ncontext, e.g. manual sends from the person tab).  This is intentional:\ngeneral candidate emails are still relevant in any application context.\nOmit the param to return all logs for the candidate regardless of\napplication (backward-compatible default).","operationId":"list_candidate_logs_api_v1_emails_logs_candidate__candidate_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}},{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailLogResponse"},"title":"Response List Candidate Logs Api V1 Emails Logs Candidate  Candidate Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/logs/{log_id}":{"get":{"tags":["emails"],"summary":"Get Log","description":"Get a single email log entry.","operationId":"get_log_api_v1_emails_logs__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/logs/{log_id}/replies":{"get":{"tags":["emails"],"summary":"List Log Replies","description":"List all inbound replies for a specific email log.","operationId":"list_log_replies_api_v1_emails_logs__log_id__replies_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailReplyResponse"},"title":"Response List Log Replies Api V1 Emails Logs  Log Id  Replies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/emails/candidate/{candidate_id}/replies":{"get":{"tags":["emails"],"summary":"List Candidate Replies","description":"List all inbound replies for a candidate, across all email logs.","operationId":"list_candidate_replies_api_v1_emails_candidate__candidate_id__replies_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailReplyResponse"},"title":"Response List Candidate Replies Api V1 Emails Candidate  Candidate Id  Replies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-integrations":{"get":{"tags":["email-integrations"],"summary":"List Integrations","description":"List the current user's connected mailboxes (no token data).","operationId":"list_integrations_api_v1_email_integrations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/EmailIntegrationResponse"},"type":"array","title":"Response List Integrations Api V1 Email Integrations Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-integrations/{integration_id}":{"delete":{"tags":["email-integrations"],"summary":"Disconnect Integration","description":"Disconnect a mailbox. Token is deleted locally; the upstream OAuth\ngrant remains until the user revokes it in their provider's account\nsettings (we don't attempt to revoke server-side because both Google\nand Microsoft handle that idempotently when the user does it themselves).","operationId":"disconnect_integration_api_v1_email_integrations__integration_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"integration_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Integration Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-integrations/google/auth-url":{"get":{"tags":["email-integrations"],"summary":"Google Auth Url","description":"Get Google OAuth consent URL for the Gmail send scope.","operationId":"google_auth_url_api_v1_email_integrations_google_auth_url_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUrlResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-integrations/google/callback":{"post":{"tags":["email-integrations"],"summary":"Google Callback","description":"Exchange the OAuth code for tokens, store them encrypted.","operationId":"google_callback_api_v1_email_integrations_google_callback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationConnectedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-integrations/microsoft/auth-url":{"get":{"tags":["email-integrations"],"summary":"Microsoft Auth Url","description":"Get Microsoft OAuth consent URL for Mail.Send.","operationId":"microsoft_auth_url_api_v1_email_integrations_microsoft_auth_url_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthUrlResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-integrations/microsoft/callback":{"post":{"tags":["email-integrations"],"summary":"Microsoft Callback","description":"Exchange the Microsoft auth code, fetch the mailbox address, store.","operationId":"microsoft_callback_api_v1_email_integrations_microsoft_callback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationConnectedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec/connect":{"post":{"tags":["itviec"],"summary":"Connect","operationId":"connect_api_v1_integrations_itviec_connect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecConnectRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec/status":{"get":{"tags":["itviec"],"summary":"Get Status","operationId":"get_status_api_v1_integrations_itviec_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec":{"delete":{"tags":["itviec"],"summary":"Disconnect","operationId":"disconnect_api_v1_integrations_itviec_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec/jobs":{"get":{"tags":["itviec"],"summary":"List Jobs","operationId":"list_jobs_api_v1_integrations_itviec_jobs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecJobsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec/jobs/{external_job_id}":{"put":{"tags":["itviec"],"summary":"Update Link","operationId":"update_link_api_v1_integrations_itviec_jobs__external_job_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"external_job_id","in":"path","required":true,"schema":{"type":"string","title":"External Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecLinkUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecJobLinkItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/integrations/itviec/settings":{"patch":{"tags":["itviec"],"summary":"Update Settings","operationId":"update_settings_api_v1_integrations_itviec_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecSettingsUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/integrations/itviec/sync":{"post":{"tags":["itviec"],"summary":"Trigger Sync","operationId":"trigger_sync_api_v1_integrations_itviec_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItviecSyncTriggerResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns/send-test":{"post":{"tags":["campaigns"],"summary":"Send Test Email","description":"Send a test email to verify campaign content before sending to the group.\n\nSends to the current user's email by default, or to a specified email address.\nVariables are replaced with sample data.","operationId":"send_test_email_api_v1_campaigns_send_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__endpoints__campaigns__SendTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns":{"get":{"tags":["campaigns"],"summary":"List Campaigns","description":"List email campaigns for the tenant.","operationId":"list_campaigns_api_v1_campaigns_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignListResponse"},"title":"Response List Campaigns Api V1 Campaigns Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["campaigns"],"summary":"Create Campaign","description":"Create a new email campaign with recipients.\n\nRecipients can come from:\n- audience_group_id: use members of a saved audience group\n- candidate_ids: manually selected candidates (backward compat)","operationId":"create_campaign_api_v1_campaigns_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}":{"get":{"tags":["campaigns"],"summary":"Get Campaign","description":"Get a single campaign with details.","operationId":"get_campaign_api_v1_campaigns__campaign_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["campaigns"],"summary":"Update Campaign","description":"Update a draft campaign.","operationId":"update_campaign_api_v1_campaigns__campaign_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["campaigns"],"summary":"Delete Campaign","description":"Delete a draft campaign and its recipients. Admin-only (broadcast tool).","operationId":"delete_campaign_api_v1_campaigns__campaign_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/send":{"post":{"tags":["campaigns"],"summary":"Send Campaign","description":"Dispatch a campaign for background sending.\n\nGated by capability ``campaign:send`` (held by Admin/Leader/Member) read from\nROLE_CAPABILITIES — so a role without it (e.g. a future read-only role) is\nrejected instead of passing on mere authentication. Tenant-scoped by\n``tenant_id``.","operationId":"send_campaign_api_v1_campaigns__campaign_id__send_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/recipients":{"get":{"tags":["campaigns"],"summary":"List Campaign Recipients","description":"List recipients for a campaign with candidate info.","operationId":"list_campaign_recipients_api_v1_campaigns__campaign_id__recipients_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignRecipientResponse"},"title":"Response List Campaign Recipients Api V1 Campaigns  Campaign Id  Recipients Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/stats":{"get":{"tags":["dashboard"],"summary":"Get Dashboard Stats","description":"Get aggregated dashboard statistics for the current tenant.","operationId":"get_dashboard_stats_api_v1_dashboard_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/overview":{"get":{"tags":["dashboard"],"summary":"Get Overview","description":"Get actionable overview data for the dashboard.","operationId":"get_overview_api_v1_dashboard_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/pending-hires":{"get":{"tags":["dashboard"],"summary":"Get Pending Hires","description":"List offers created by current user with accepted status + start_date\nđã tới (<= hôm nay) nhưng application còn active (chờ HR confirm\nhired/no-show).\n\nGate `start_date <= today` khớp với cron `check_hire_confirmations` và\ncount trong `/dashboard/summary` — popup chỉ hiện sáng đúng ngày ứng viên\ndự kiến đi làm để recruiter confirm, không hiện sớm (câu hỏi \"đã đi làm\nhôm nay chưa?\" chỉ đúng khi start_date <= today). Nếu ứng viên đi làm sớm\nhơn dự kiến, HR dùng PostponeStartDateModal kéo start_date về ngày thực\ntế trước rồi Confirm Hired.","operationId":"get_pending_hires_api_v1_dashboard_pending_hires_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PendingHireItem"},"type":"array","title":"Response Get Pending Hires Api V1 Dashboard Pending Hires Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reports":{"get":{"tags":["reports"],"summary":"Get Report","description":"Get aggregated recruitment report for the given date range.\n\nPR2 scope: a Member sees only jobs they own; the recruiter filter is locked\nto themselves. Admin/Leader are tenant-wide.","operationId":"get_report_api_v1_reports_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Start date (YYYY-MM-DD)","title":"Start Date"},"description":"Start date (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"End date (YYYY-MM-DD)","title":"End Date"},"description":"End date (YYYY-MM-DD)"},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by job","title":"Job Id"},"description":"Optional: filter by job"},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by department(s)","title":"Department"},"description":"Filter by department(s)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by applicant status","title":"Status"},"description":"Filter by applicant status"},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"},{"name":"pipeline_template_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: scope report to one hiring-pipeline template + label the funnel by its stage names","title":"Pipeline Template Id"},"description":"Optional: scope report to one hiring-pipeline template + label the funnel by its stage names"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/export":{"get":{"tags":["reports"],"summary":"Export Report","description":"Export recruitment report as Excel (.xlsx).\n\nSheets:\n  1. Summary — KPI metrics with prev-period delta\n  2. Pipeline — stage counts + conversion rates\n  3. Sources — source effectiveness\n  4. Recruiters — recruiter performance\n  5. Jobs — trend (opened vs closed), status × department, employment type, work setup\n  6. Applications — one row per application (for custom pivots)\n  7. Stage transitions — one row per stage/status change\n\nPR2 scope: a Member's export is restricted to jobs they own (every sheet,\nincl. the raw PII Applications sheet and the Recruiters sheet which is\nself-locked) — not tenant-wide.","operationId":"export_report_api_v1_reports_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by applicant status","title":"Status"},"description":"Filter by applicant status"},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"},{"name":"pipeline_template_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: scope to one hiring-pipeline template","title":"Pipeline Template Id"},"description":"Optional: scope to one hiring-pipeline template"},{"name":"lang","in":"query","required":false,"schema":{"type":"string","description":"Locale for sheet titles + headers: vi | en","default":"vi","title":"Lang"},"description":"Locale for sheet titles + headers: vi | en"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/export-pdf":{"get":{"tags":["reports"],"summary":"Export Pdf","description":"Export recruitment report as a server-side PDF via Typst.\n\nParallel to the client-side React-PDF export — no browser required.\nThe template is ``app/assets/report/report.typ``; fonts are bundled under\n``app/assets/report/fonts/``.\n\nPR2 scope: same RBAC narrowing as ``/export`` (Excel) — a Member's PDF\nis restricted to jobs they own.","operationId":"export_pdf_api_v1_reports_export_pdf_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by applicant status","title":"Status"},"description":"Filter by applicant status"},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"},{"name":"lang","in":"query","required":false,"schema":{"type":"string","description":"Locale for labels and dates: vi | en","default":"vi","title":"Lang"},"description":"Locale for labels and dates: vi | en"},{"name":"sections","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated section ids to include (kpi, kpi_history, funnel, stage, stage_duration, pipeline_snapshot, trend, sources, demographics, hired_list, offers, top_jobs, recruiters, jobs). Omit to include all data-backed sections.","title":"Sections"},"description":"Comma-separated section ids to include (kpi, kpi_history, funnel, stage, stage_duration, pipeline_snapshot, trend, sources, demographics, hired_list, offers, top_jobs, recruiters, jobs). Omit to include all data-backed sections."},{"name":"report_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Override the cover page title.","title":"Report Name"},"description":"Override the cover page title."},{"name":"prepared_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Override the preparedBy field on the cover.","title":"Prepared By"},"description":"Override the preparedBy field on the cover."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/hired-list":{"get":{"tags":["reports"],"summary":"Hired List","description":"Get paginated list of hired candidates (Member: owned jobs only).","operationId":"hired_list_api_v1_reports_hired_list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"hired_date","title":"Sort By"}},{"name":"sort_dir","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"desc","title":"Sort Dir"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HiredListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/offer-list":{"get":{"tags":["reports"],"summary":"Offer List","description":"Paginated offer letters sent in [start_date, end_date], latest version\nper application (Member: owned jobs only).","operationId":"offer_list_api_v1_reports_offer_list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","pattern":"^(sent_at|candidate_name|status|start_date)$","default":"sent_at","title":"Sort By"}},{"name":"sort_dir","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"desc","title":"Sort Dir"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/offer-kpis":{"get":{"tags":["reports"],"summary":"Offer Kpis","description":"Two KPI ratios for Offer Tracking (Member: owned jobs only).","operationId":"offer_kpis_api_v1_reports_offer_kpis_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferKpisResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/applications-list":{"get":{"tags":["reports"],"summary":"Applications List","description":"Drill-down list of the applications behind a report number.\n\nSame cohort/eligibility as the count metrics so the list reconciles with the\nnumber it backs (no filter = active_candidates cohort by application;\nstatus=hired = compute.count_hired). Member: owned jobs only.","operationId":"applications_list_api_v1_reports_applications_list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(active|hired|rejected)$"},{"type":"null"}],"title":"Status"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional: raw Candidate.source (exact)","title":"Source"},"description":"Optional: raw Candidate.source (exact)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"effective_entry_date","title":"Sort By"}},{"name":"sort_dir","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","default":"desc","title":"Sort Dir"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/source-matrix":{"get":{"tags":["reports"],"summary":"Source Matrix","description":"Get source × stage matrix data (Member: owned jobs only).","operationId":"source_matrix_api_v1_reports_source_matrix_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMatrixResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/demographics":{"get":{"tags":["reports"],"summary":"Demographics","description":"Get candidate demographics (gender & location distribution) — Member: owned jobs only.","operationId":"demographics_api_v1_reports_demographics_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemographicsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/time-to-fill":{"get":{"tags":["reports"],"summary":"Time To Fill","description":"Get time-to-fill metrics (Member: owned jobs only).","operationId":"time_to_fill_api_v1_reports_time_to_fill_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeToFillMetric"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/jobs-overview":{"get":{"tags":["reports"],"summary":"Jobs Overview","description":"Aggregated job-level statistics for the Reports page Job Metrics group.\n\nReturns:\n  - trend: opened vs closed jobs per time bucket (granularity auto-picked)\n  - status_by_department: stacked bar data (Open/Closed/On-hold × top 5 depts + \"Khác\")\n  - by_employment_type: donut data (full_time / part_time / contract / internship)\n  - by_work_setup: donut data (onsite / hybrid / remote / flexible)\n\nPR2 scope: job-grain only (no recruiter dimension); a Member sees the\noverview restricted to jobs they own.","operationId":"jobs_overview_api_v1_reports_jobs_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Start Date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"End Date"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsOverviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/kpi-history":{"get":{"tags":["reports"],"summary":"Kpi History","description":"Month-over-Month KPI history: headline metrics for ``periods`` equal-length\nwindows walking back from [start_date, end_date] (index 0 = current period).\n\nEach bucket carries total_hired, total_applications (entry cohort), and\noffer_acceptance_rate. ``periods`` capped at 12. Member: owned jobs only.","operationId":"kpi_history_api_v1_reports_kpi_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Start of the current period (YYYY-MM-DD)","title":"Start Date"},"description":"Start of the current period (YYYY-MM-DD)"},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"End of the current period (YYYY-MM-DD)","title":"End Date"},"description":"End of the current period (YYYY-MM-DD)"},{"name":"periods","in":"query","required":false,"schema":{"type":"integer","maximum":12,"minimum":1,"description":"How many equal-length periods (back from current)","default":6,"title":"Periods"},"description":"How many equal-length periods (back from current)"},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Department"}},{"name":"recruiter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Optional: filter by recruiter","title":"Recruiter Id"},"description":"Optional: filter by recruiter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KpiHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/settings":{"get":{"tags":["reports"],"summary":"Get Settings","description":"Get report settings for the current user.","operationId":"get_settings_api_v1_reports_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["reports"],"summary":"Update Settings","description":"Upsert report settings for the current user.","operationId":"update_settings_api_v1_reports_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportSettingsData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/exports":{"post":{"tags":["exports"],"summary":"Create Export","description":"Create a new export job and dispatch background processing.","operationId":"create_export_api_v1_exports_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportJobCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["exports"],"summary":"List Exports","description":"List recent export jobs (last 30 days) for the tenant.","operationId":"list_exports_api_v1_exports_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExportJobStatusResponse"},"title":"Response List Exports Api V1 Exports Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/exports/{export_id}":{"get":{"tags":["exports"],"summary":"Get Export Status","description":"Poll an export job's status (tenant-scoped).","operationId":"get_export_status_api_v1_exports__export_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"export_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Export Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportJobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/onboarding/status":{"get":{"tags":["onboarding"],"summary":"Get Onboarding Status","description":"Get current onboarding state with pre-filled data.","operationId":"get_onboarding_status_api_v1_onboarding_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/step/1":{"put":{"tags":["onboarding"],"summary":"Save Step Profile","description":"Save step 1: user profile data.","operationId":"save_step_profile_api_v1_onboarding_step_1_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepProfileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/step/2":{"put":{"tags":["onboarding"],"summary":"Save Step Company","description":"Save step 2: company info.\n\nAdmin-only: company identity (name, logo, industry) is a tenant-level\nresource. Invited members land in a workspace that already exists, so they\nmust not be able to rewrite the company name during onboarding (RBAC v2.2 —\nthe frontend skips this step for non-admins; this guard is the enforcement).","operationId":"save_step_company_api_v1_onboarding_step_2_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepCompanyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/step/3":{"put":{"tags":["onboarding"],"summary":"Save Step Recruitment","description":"Save step 3: recruitment goals.\n\nAdmin-only for the same reason as step 2 — monthly volume + hiring\nchallenges are tenant-level config the workspace owner sets, not invited\nmembers.","operationId":"save_step_recruitment_api_v1_onboarding_step_3_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepRecruitmentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/complete":{"post":{"tags":["onboarding"],"summary":"Complete Onboarding","description":"Mark onboarding as complete and return redirect path.","operationId":"complete_onboarding_api_v1_onboarding_complete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCompleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCompleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/skip":{"post":{"tags":["onboarding"],"summary":"Skip Onboarding","description":"Skip onboarding entirely.","operationId":"skip_onboarding_api_v1_onboarding_skip_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingCompleteResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/checklist":{"get":{"tags":["onboarding"],"summary":"Get Checklist","description":"First-Day Magic: per-tenant checklist progress for floating widget.","operationId":"get_checklist_api_v1_onboarding_checklist_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/checklist/dismiss":{"post":{"tags":["onboarding"],"summary":"Dismiss Checklist","description":"Per-tenant dismiss: hides the floating widget for the whole team.","operationId":"dismiss_checklist_api_v1_onboarding_checklist_dismiss_post","responses":{"204":{"description":"Successful Response"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/onboarding/demo":{"delete":{"tags":["onboarding"],"summary":"Clear Demo Data","description":"Wipe is_demo=True rows for this tenant + un-tick demo-derived progress.\n\nCascade order respects FK constraints (manual cascade because applications\nhas no soft delete; we hard-delete demo rows + dependents in dep order).\nReal (non-demo) data is untouched.","operationId":"clear_demo_data_api_v1_onboarding_demo_delete","responses":{"204":{"description":"Successful Response"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/public/pages/sitemap":{"get":{"tags":["public-pages"],"summary":"List Sitemap Pages","description":"List all published pages with subdomains for sitemap generation.\nNo authentication required - this is a public endpoint.","operationId":"list_sitemap_pages_api_v1_public_pages_sitemap_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SitemapPageEntry"},"type":"array","title":"Response List Sitemap Pages Api V1 Public Pages Sitemap Get"}}}}}}},"/api/v1/public/pages/subdomains":{"get":{"tags":["public-pages"],"summary":"List Public Subdomains","description":"List the subdomains that resolve to a live career page — same filter as\n`by-subdomain` (published, not deleted, active tenant), so the edge gate\nmirrors origin behavior exactly. Consumed by the frontend Worker\nmiddleware (Gate 7, docs/plans/2026-08-08-neon-cost-renovation.md §4) to\nanswer junk-subdomain probes without touching the database. Long edge TTL;\nevery career purge evicts this URL, so publishes go live in seconds.\n\nServed from process memory (`subdomain_list_cache`) — deliberately NO DB\nsession here: Cloudflare caches this URL per data center, so every colo's\nfirst miss reaches origin (~53×/day, the top night-time Neon waker before\n2026-08-21). The cache refreshes on boot, at the hourly :00 sweep, and on\nevery career publish/unpublish/rename/delete (same hook as the edge purge).","operationId":"list_public_subdomains_api_v1_public_pages_subdomains_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubdomainListResponse"}}}}}}},"/api/v1/public/pages/by-subdomain/{subdomain}":{"get":{"tags":["public-pages"],"summary":"Get Page By Subdomain","description":"Get a published page by its per-page subdomain.\nNo authentication required - this is a public endpoint.","operationId":"get_page_by_subdomain_api_v1_public_pages_by_subdomain__subdomain__get","parameters":[{"name":"subdomain","in":"path","required":true,"schema":{"type":"string","title":"Subdomain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/pages/{tenant_code}/{slug}":{"get":{"tags":["public-pages"],"summary":"Get Public Page","description":"Get a published page by tenant code and slug.\nNo authentication required - this is a public endpoint.","operationId":"get_public_page_api_v1_public_pages__tenant_code___slug__get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}},{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/jobs/{tenant_code}":{"get":{"tags":["public-jobs"],"summary":"Get Public Jobs","description":"List open jobs for a tenant's public career page.\nLooks up tenant by company_code or subdomain (case-insensitive).","operationId":"get_public_jobs_api_v1_public_jobs__tenant_code__get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}},{"name":"department","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"}},{"name":"employment_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/EmploymentType"},{"type":"null"}],"title":"Employment Type"}},{"name":"work_setup","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicJobPaginatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/jobs/{tenant_code}/filters":{"get":{"tags":["public-jobs"],"summary":"Get Public Job Filters","description":"Return distinct departments, locations, employment types from open jobs.","operationId":"get_public_job_filters_api_v1_public_jobs__tenant_code__filters_get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicJobFiltersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/jobs/{tenant_code}/{job_identifier}":{"get":{"tags":["public-jobs"],"summary":"Get Public Job Detail","description":"Get single job detail for the public career page.\n\nAccepts either a UUID (for backwards compatibility) or a slug.","operationId":"get_public_job_detail_api_v1_public_jobs__tenant_code___job_identifier__get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}},{"name":"job_identifier","in":"path","required":true,"schema":{"type":"string","title":"Job Identifier"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicJobDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/blog/posts":{"get":{"tags":["public-blog"],"summary":"List Public Posts","description":"List published public posts, newest first (published_at desc).","operationId":"list_public_posts_api_v1_public_blog_posts_get","parameters":[{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag slug","title":"Tag"},"description":"Filter by tag slug"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlogPostList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/blog/tags":{"get":{"tags":["public-blog"],"summary":"List Public Tags","description":"List tags that have at least one published public post.","operationId":"list_public_tags_api_v1_public_blog_tags_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PublicBlogTag"},"type":"array","title":"Response List Public Tags Api V1 Public Blog Tags Get"}}}}}}},"/api/v1/public/blog/posts/{slug}":{"get":{"tags":["public-blog"],"summary":"Get Public Post","description":"Get one published public post by slug. 404 if missing/draft/deleted.","operationId":"get_public_post_api_v1_public_blog_posts__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBlogPostDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/blog/subscribe":{"post":{"tags":["public-blog"],"summary":"Subscribe To Blog","description":"Public newsletter signup (double opt-in). Always returns a generic\n``pending`` ack — never reveals whether the address was already on the list.","operationId":"subscribe_to_blog_api_v1_public_blog_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/blog/confirm":{"get":{"tags":["public-blog"],"summary":"Confirm Subscription","description":"Confirm a double-opt-in magic link. Idempotent.","operationId":"confirm_subscription_api_v1_public_blog_confirm_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","minLength":10,"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/blog/unsubscribe":{"post":{"tags":["public-blog"],"summary":"Unsubscribe From Blog","description":"Unsubscribe by the subscriber's public uuid. Idempotent — repeat clicks\nreturn the same result without error.","operationId":"unsubscribe_from_blog_api_v1_public_blog_unsubscribe_post","parameters":[{"name":"uuid","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Uuid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/application-form/config":{"get":{"tags":["application-form"],"summary":"Get Form Config","description":"Get all form field configs for the current tenant (auth required).","operationId":"get_form_config_api_v1_application_form_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ApplicationFormConfigResponse"},"type":"array","title":"Response Get Form Config Api V1 Application Form Config Get"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["application-form"],"summary":"Update Form Config","description":"Bulk update form field configs for the current tenant.","operationId":"update_form_config_api_v1_application_form_config_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationFormConfigBulkUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ApplicationFormConfigResponse"},"type":"array","title":"Response Update Form Config Api V1 Application Form Config Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/application-form/public/{tenant_code}":{"get":{"tags":["application-form"],"summary":"Get Public Form Config","description":"Get enabled form fields for the public application form (no auth).\n\nReturns enriched metadata (field_type, step, options, validation, etc.)\nso the frontend can render dynamically without hardcoded field definitions.","operationId":"get_public_form_config_api_v1_application_form_public__tenant_code__get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApplicationFormConfigPublicResponse"},"title":"Response Get Public Form Config Api V1 Application Form Public  Tenant Code  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/application-form/additional-questions":{"get":{"tags":["application-form"],"summary":"List Additional Questions","description":"Admin view of tenant's additional questions (all, incl. disabled).","operationId":"list_additional_questions_api_v1_application_form_additional_questions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AdditionalQuestionResponse"},"type":"array","title":"Response List Additional Questions Api V1 Application Form Additional Questions Get"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["application-form"],"summary":"Replace Additional Questions","description":"Replace-all bulk update.\n\nExisting rows whose ``id`` isn't in the payload are deleted (hard delete —\nthe historical answer is already snapshotted onto ``applications.additional_answers``,\nso removing the config row can't corrupt history).","operationId":"replace_additional_questions_api_v1_application_form_additional_questions_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdditionalQuestionsBulkUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AdditionalQuestionResponse"},"type":"array","title":"Response Replace Additional Questions Api V1 Application Form Additional Questions Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/application-form/public/{tenant_code}/additional-questions":{"get":{"tags":["application-form"],"summary":"Get Public Additional Questions","description":"Return the enabled additional questions for the public apply form.","operationId":"get_public_additional_questions_api_v1_application_form_public__tenant_code__additional_questions_get","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AdditionalQuestionPublicResponse"},"title":"Response Get Public Additional Questions Api V1 Application Form Public  Tenant Code  Additional Questions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/applications/pre-parse-cv":{"post":{"tags":["public-applications"],"summary":"Pre Parse Cv","description":"Extract name/email/phone from a CV file without AI.\n\nUsed by the career page form to auto-fill contact fields from the uploaded CV.\nFast regex extraction only — no LLM, no async queue, no candidate created.\nMax 5MB. PDF/DOCX/DOC autofill; image CVs are accepted but return an empty\nautofill (reading them needs paid OCR, which must never run on this\nunauthenticated path — the real parse happens post-submit under the\ntenant's vision cap).","operationId":"pre_parse_cv_api_v1_public_applications_pre_parse_cv_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_pre_parse_cv_api_v1_public_applications_pre_parse_cv_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreParseCvResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/applications/submit/{tenant_code}":{"post":{"tags":["public-applications"],"summary":"Submit Public Application","description":"Public endpoint for candidates to submit job applications.\nAccepts multipart/form-data. No authentication required.\n\nFields are parsed dynamically from the form data and validated\nagainst the tenant's form config + FORM_FIELD_REGISTRY.","operationId":"submit_public_application_api_v1_public_applications_submit__tenant_code__post","parameters":[{"name":"tenant_code","in":"path","required":true,"schema":{"type":"string","title":"Tenant Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/emails/unsubscribe/{token}":{"get":{"tags":["public-emails"],"summary":"Unsubscribe","description":"Public endpoint to unsubscribe a candidate from automated emails.\n\nLooks up the EmailLog by reply_token, finds the candidate, and marks them\nas unsubscribed. Idempotent — already unsubscribed shows success.","operationId":"unsubscribe_api_v1_public_emails_unsubscribe__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-emails"],"summary":"Unsubscribe One Click","description":"RFC 8058 one-click unsubscribe (Microsoft/Gmail bulk sender requirement).\n\nMail providers POST here with body `List-Unsubscribe=One-Click` when the\nuser clicks the unsubscribe action in the mail client UI. We intentionally\nreturn 204 regardless of token validity so callers can't enumerate tokens.","operationId":"unsubscribe_one_click_api_v1_public_emails_unsubscribe__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/events/track":{"post":{"tags":["public-events"],"summary":"Track Event","description":"Log a growth event. Fire-and-forget — always returns 204.","operationId":"track_event_api_v1_public_events_track_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPayload"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/handbook/feedback":{"post":{"tags":["public-handbook"],"summary":"Submit Handbook Feedback","description":"Record one feedback row. Returns ok + timestamp; no PII echoed back.","operationId":"submit_handbook_feedback_api_v1_public_handbook_feedback_post","parameters":[{"name":"user-agent","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User-Agent"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandbookFeedbackIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandbookFeedbackOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/hm-reviews/request":{"post":{"tags":["hm-reviews"],"summary":"Create Hm Review Request","description":"Create an HM review request — optionally sends email to reviewer.","operationId":"create_hm_review_request_api_v1_hm_reviews_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HMReviewRequestCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HMReviewRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/hm-reviews/requests":{"get":{"tags":["hm-reviews"],"summary":"List Hm Reviews","description":"List HM review requests for a tenant, optionally filtered.","operationId":"list_hm_reviews_api_v1_hm_reviews_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"application_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}},{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(pending|passed|not_passed)$"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HMReviewListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/hm-reviews/requests/{review_id}":{"get":{"tags":["hm-reviews"],"summary":"Get Hm Review","description":"Get a single HM review request.","operationId":"get_hm_review_api_v1_hm_reviews_requests__review_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HMReviewRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/hm-reviews/requests/{review_id}/cancel":{"post":{"tags":["hm-reviews"],"summary":"Cancel Hm Review","description":"Cancel a pending HM review request.","operationId":"cancel_hm_review_api_v1_hm_reviews_requests__review_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/hm-reviews/requests/{review_id}/resend":{"post":{"tags":["hm-reviews"],"summary":"Resend Hm Review","description":"Resend the HM review email with a new token.","operationId":"resend_hm_review_api_v1_hm_reviews_requests__review_id__resend_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/hm-reviews/batch-request":{"post":{"tags":["hm-reviews"],"summary":"Create Batch Hm Review Request","description":"Create a batch HM review — send multiple candidates to multiple reviewers.","operationId":"create_batch_hm_review_request_api_v1_hm_reviews_batch_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchHMReviewRequestCreate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchHMReviewRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/hm-reviews/batch/{batch_id}/remind":{"post":{"tags":["hm-reviews"],"summary":"Remind Batch Hm Review","description":"Send a reminder for pending evaluations in a batch.","operationId":"remind_batch_hm_review_api_v1_hm_reviews_batch__batch_id__remind_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Batch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/hm-reviews/review/{token}":{"get":{"tags":["public-hm-reviews"],"summary":"Get Hm Review Context","description":"Get the review context for a Hiring Manager (public, token-based).","operationId":"get_hm_review_context_api_v1_public_hm_reviews_review__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-hm-reviews"],"summary":"Submit Hm Review Decision","description":"Submit a Pass/Not Pass decision (public, token-based).","operationId":"submit_hm_review_decision_api_v1_public_hm_reviews_review__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewDecisionSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewDecisionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/hm-reviews/batch/{token}":{"get":{"tags":["public-hm-reviews"],"summary":"Get Batch Hm Review Context","description":"Get the batch review context for a Hiring Manager (public, token-based).","operationId":"get_batch_hm_review_context_api_v1_public_hm_reviews_batch__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicBatchHMReviewContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-hm-reviews"],"summary":"Submit Batch Hm Review","description":"Submit all decisions for a batch review — atomic commit.","operationId":"submit_batch_hm_review_api_v1_public_hm_reviews_batch__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDecisionSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewDecisionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/hm-reviews/batch/{token}/draft":{"patch":{"tags":["public-hm-reviews"],"summary":"Save Batch Draft","description":"Save draft decisions for a batch review (auto-save).","operationId":"save_batch_draft_api_v1_public_hm_reviews_batch__token__draft_patch","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDraftSave"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/hm-reviews/batch/{token}/decisions/{evaluation_id}":{"post":{"tags":["public-hm-reviews"],"summary":"Submit Batch Eval Decision","description":"Submit a single candidate's decision in a batch (rolling submit).\n\nPer-candidate finalization. Each call marks ONE evaluation as decided,\nfires recruiter notification + pipeline auto-advance for that candidate\nonly. Remaining un-finalized candidates stay editable. When the last\none is decided, the batch token is automatically marked as used.","operationId":"submit_batch_eval_decision_api_v1_public_hm_reviews_batch__token__decisions__evaluation_id__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}},{"name":"evaluation_id","in":"path","required":true,"schema":{"type":"string","title":"Evaluation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewDecisionSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicHMReviewDecisionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/cv/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Candidate Cv","description":"Redirect to candidate CV file for interviewers. No auth required.","operationId":"get_candidate_cv_api_v1_public_interviews_cv__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/candidate/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Candidate Profile","description":"Read-only candidate summary for interviewers. No auth required.","operationId":"get_candidate_profile_api_v1_public_interviews_candidate__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCandidateProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/candidate-detail/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Candidate Detail","description":"Full candidate detail for interviewers. Token IS the authorization.","operationId":"get_candidate_detail_api_v1_public_interviews_candidate_detail__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCandidateDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/feedback/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Feedback Context","description":"Get interview context for the feedback form. No auth required.\n\nAlso serves the \"already submitted\" readonly view: if the token is used\n(is_used=True), fetch the previously submitted Evaluation and return it\ninline via `submitted` so the FE can render a readonly recap instead of\n404. Mirrors public_hm_reviews.get_hm_review_context.","operationId":"get_feedback_context_api_v1_public_interviews_feedback__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFeedbackContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-interviews"],"summary":"Submit Feedback","description":"Submit post-interview feedback from an external interviewer. No auth.\n\nRestored 2026-06-09. This is the interviewer's evaluation AFTER conducting\nthe interview — a SEPARATE flow from HM Review (HM Review is the\npre-interview CV screening, which stays untouched). Writes an Evaluation row\n(``evaluation_type='interview_feedback'``, ``source='external_token'``) plus\na copy in ``interview.feedback_data.submissions`` for the interview-centric\nview. The token is one-time use; if a fresh feedback_form token is later\nissued to the same interviewer (e.g. on reschedule), their entry in\n``feedback_data.submissions`` is replaced (the ``evaluations`` table keeps\neach submission as its own row).\n\nDouble-submit protection: `_validate_token` returns None for used tokens;\nwe surface a clearer 400 \"Already submitted\" (instead of the generic 404)\nso the FE can point the interviewer at the readonly recap flow.","operationId":"submit_feedback_api_v1_public_interviews_feedback__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFeedbackSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicFeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/respond/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Interview Response Context","description":"Get interview context for the candidate accept/decline page.","operationId":"get_interview_response_context_api_v1_public_interviews_respond__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewResponseContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-interviews"],"summary":"Submit Interview Response","description":"Submit candidate's accept/decline response.","operationId":"submit_interview_response_api_v1_public_interviews_respond__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewResponseSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewResponseResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/interviewer-respond/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Interviewer Response Context","description":"Get interview context for the interviewer accept/decline page.","operationId":"get_interviewer_response_context_api_v1_public_interviews_interviewer_respond__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewerResponseContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-interviews"],"summary":"Submit Interviewer Response","description":"Submit interviewer's accept/decline response.","operationId":"submit_interviewer_response_api_v1_public_interviews_interviewer_respond__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewerResponseSubmit"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicInterviewerResponseResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/interviews/schedule/{token}":{"get":{"tags":["public-interviews"],"summary":"Get Self Schedule Context","description":"Get available time slots for candidate self-scheduling.","operationId":"get_self_schedule_context_api_v1_public_interviews_schedule__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSelfScheduleContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["public-interviews"],"summary":"Select Self Schedule Slot","description":"Candidate selects a time slot -- finalizes the interview schedule.","operationId":"select_self_schedule_slot_api_v1_public_interviews_schedule__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSelfScheduleSelect"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSelfScheduleResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/usage/summary":{"get":{"tags":["usage"],"summary":"Usage Summary","description":"Return current plan limits and usage counts for the tenant.","operationId":"usage_summary_api_v1_usage_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummaryResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/locations/countries":{"get":{"tags":["locations"],"summary":"List Countries","description":"List all countries (250 items, cached 24h).","operationId":"list_countries_api_v1_locations_countries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CountryResponse"},"type":"array","title":"Response List Countries Api V1 Locations Countries Get"}}}}}}},"/api/v1/locations/countries/{iso2}/states":{"get":{"tags":["locations"],"summary":"List States By Country","description":"List states/provinces for a country by ISO2 code (cached 24h).","operationId":"list_states_by_country_api_v1_locations_countries__iso2__states_get","parameters":[{"name":"iso2","in":"path","required":true,"schema":{"type":"string","title":"Iso2"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StateResponse"},"title":"Response List States By Country Api V1 Locations Countries  Iso2  States Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/locations/states/{state_id}/cities":{"get":{"tags":["locations"],"summary":"Search Cities","description":"Search cities within a state (server-side search, limit 50).\n\nRequires min 2 chars for search query to return results.","operationId":"search_cities_api_v1_locations_states__state_id__cities_get","parameters":[{"name":"state_id","in":"path","required":true,"schema":{"type":"integer","title":"State Id"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","minLength":0,"default":"","title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CityResponse"},"title":"Response Search Cities Api V1 Locations States  State Id  Cities Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/locations/vn-provinces":{"get":{"tags":["locations"],"summary":"List Vn Provinces","description":"List all Vietnamese provinces (63 items, cached 24h).","operationId":"list_vn_provinces_api_v1_locations_vn_provinces_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/VnProvinceResponse"},"type":"array","title":"Response List Vn Provinces Api V1 Locations Vn Provinces Get"}}}}}}},"/api/v1/notifications":{"get":{"tags":["notifications"],"summary":"List Notifications","description":"List notifications for the current user, newest first.","operationId":"list_notifications_api_v1_notifications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/unread-count":{"get":{"tags":["notifications"],"summary":"Get Unread Count","description":"Lightweight endpoint for badge polling. Optionally filter by type and/or entity_id.","operationId":"get_unread_count_api_v1_notifications_unread_count_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by notification type","title":"Type"},"description":"Filter by notification type"},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by entity ID","title":"Entity Id"},"description":"Filter by entity ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnreadCountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/read":{"patch":{"tags":["notifications"],"summary":"Mark Read","description":"Mark specific notifications as read.","operationId":"mark_read_api_v1_notifications_read_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/notifications/read-by-candidate/{candidate_id}":{"patch":{"tags":["notifications"],"summary":"Mark Read By Candidate","description":"Mark all unread notifications for a specific candidate as read.\n\nMatches notifications where metadata contains the candidate_id.","operationId":"mark_read_by_candidate_api_v1_notifications_read_by_candidate__candidate_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/read-by-entity/{entity_type}/{entity_id}":{"patch":{"tags":["notifications"],"summary":"Mark Read By Entity","description":"Mark all unread notifications for a specific entity as read.","operationId":"mark_read_by_entity_api_v1_notifications_read_by_entity__entity_type___entity_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"entity_type","in":"path","required":true,"schema":{"type":"string","title":"Entity Type"}},{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/read-all":{"patch":{"tags":["notifications"],"summary":"Mark All Read","description":"Mark all notifications as read.","operationId":"mark_all_read_api_v1_notifications_read_all_patch","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/notifications/preferences":{"get":{"tags":["notifications"],"summary":"Get Preferences","description":"Return current user's per-type prefs (in-app + email) merged with defaults.","operationId":"get_preferences_api_v1_notifications_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferenceResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["notifications"],"summary":"Update Preferences","description":"Patch prefs. Any of email_enabled / email_preferences / inapp_preferences\ncan be omitted; provided dicts are merged into the stored JSONB, not replaced.","operationId":"update_preferences_api_v1_notifications_preferences_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferenceUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferenceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sources":{"get":{"tags":["sources"],"summary":"List Sources","description":"Return all fixed sources + tenant's custom sources.","operationId":"list_sources_api_v1_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SourceResponse"},"type":"array","title":"Response List Sources Api V1 Sources Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["sources"],"summary":"Create Custom Source","description":"Create a new custom source for the tenant.","operationId":"create_custom_source_api_v1_sources_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomSourceCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sources/{value}/career-form":{"patch":{"tags":["sources"],"summary":"Set Source Career Form","description":"HR bật/tắt MỘT nguồn trên form ứng tuyển công khai — một đường cho cả hai\nloại dòng của ô tick trong Profile Builder:\n\n- ``value`` là Loại chuẩn (``STANDARD_SOURCE_VALUES``: linkedin, facebook,\n  job_board, other_social, career_page, referral, other): cờ nằm trong\n  ``tenant.settings[\"career_form_sources\"][\"visible\"]`` (quyết định\n  16/09/2026 — trước đó 7 Loại này luôn hiện, không tắt được). Khoá dòng\n  tenant (``FOR UPDATE``) vì ``settings`` là một dict đọc-sửa-ghi: hai lần\n  tick liền nhau không khoá sẽ đè mất nhau.\n- ngược lại: nguồn riêng của CHÍNH tenant (tra theo tenant_id + slug), cờ\n  ``custom_sources.show_on_career_form`` (migration 244).\n\nSlug nguồn riêng không bao giờ trùng Loại chuẩn (``create_custom_source``\nchặn 409), nên ``value`` phân biệt được hai nhánh. Built-in ngoài form công\nkhai (email, hr...) hoặc slug lạ -> 404. Form công khai đọc cờ qua\n``career_form_sources`` ngay ở lần tải sau, không có cache trung gian.","operationId":"set_source_career_form_api_v1_sources__value__career_form_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"value","in":"path","required":true,"schema":{"type":"string","title":"Value"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceCareerFormUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/source-management/values":{"get":{"tags":["source-management"],"summary":"List Source Values","description":"Return distinct (source, source_detail) pairs with candidate counts.\n\nOrdered by count descending.  Only non-deleted candidates are counted.","operationId":"list_source_values_api_v1_source_management_values_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceValuesResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/source-management/apply":{"post":{"tags":["source-management"],"summary":"Apply Source Operation","description":"Apply a source-normalization operation to matching candidates.\n\nSet ``dry_run=true`` to preview the affected count without writing.\nWhen ``dry_run=false`` (default), writes the batch and cascades the update\nto all matching candidates in one transaction.","operationId":"apply_source_operation_api_v1_source_management_apply_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/source-management/undo":{"post":{"tags":["source-management"],"summary":"Undo Last Operation","description":"Undo the most recent un-reversed batch for this tenant.\n\nRestores each candidate back to its pre-operation (source, source_detail)\nand marks the batch row with ``undone_at``.  Returns 404 when there is no\nundoable batch.","operationId":"undo_last_operation_api_v1_source_management_undo_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndoResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/source-management/history":{"get":{"tags":["source-management"],"summary":"Get Operation History","description":"Return the source-cleanup operation history for this tenant.\n\nOrdered newest-first.  Includes both undone and active batches so the\nadmin can see the full audit trail.","operationId":"get_operation_history_api_v1_source_management_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaign-templates":{"get":{"tags":["campaign-templates"],"summary":"List Campaign Templates","description":"List campaign templates (system + tenant custom).","operationId":"list_campaign_templates_api_v1_campaign_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignTemplateListResponse"},"title":"Response List Campaign Templates Api V1 Campaign Templates Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["campaign-templates"],"summary":"Create Campaign Template","description":"Create a tenant-custom campaign template.","operationId":"create_campaign_template_api_v1_campaign_templates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTemplateCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaign-templates/{template_id}":{"get":{"tags":["campaign-templates"],"summary":"Get Campaign Template","description":"Get a single campaign template.","operationId":"get_campaign_template_api_v1_campaign_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["campaign-templates"],"summary":"Update Campaign Template","description":"Update a tenant-custom campaign template. System templates cannot be edited.","operationId":"update_campaign_template_api_v1_campaign_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["campaign-templates"],"summary":"Delete Campaign Template","description":"Soft delete a tenant-custom campaign template.","operationId":"delete_campaign_template_api_v1_campaign_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audience-groups/preview":{"post":{"tags":["audience-groups"],"summary":"Preview Filter","description":"Preview how many candidates match filter criteria (without saving).\n\nApplies safety exclusions: hired, active in pipeline, blacklisted, no email.","operationId":"preview_filter_api_v1_audience_groups_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceFilterPreview"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/audience-groups":{"get":{"tags":["audience-groups"],"summary":"List Audience Groups","description":"List all audience groups for the tenant.","operationId":"list_audience_groups_api_v1_audience_groups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AudienceGroupListResponse"},"type":"array","title":"Response List Audience Groups Api V1 Audience Groups Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["audience-groups"],"summary":"Create Audience Group","description":"Create an audience group with optional initial members.","operationId":"create_audience_group_api_v1_audience_groups_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/audience-groups/{group_id}":{"get":{"tags":["audience-groups"],"summary":"Get Audience Group","description":"Get a single audience group.","operationId":"get_audience_group_api_v1_audience_groups__group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["audience-groups"],"summary":"Update Audience Group","description":"Update an audience group's name, description, or filter settings.","operationId":"update_audience_group_api_v1_audience_groups__group_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["audience-groups"],"summary":"Delete Audience Group","description":"Soft delete an audience group.","operationId":"delete_audience_group_api_v1_audience_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audience-groups/{group_id}/members":{"get":{"tags":["audience-groups"],"summary":"List Group Members","description":"List members of an audience group with candidate info.","operationId":"list_group_members_api_v1_audience_groups__group_id__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":500,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AudienceGroupMemberResponse"},"title":"Response List Group Members Api V1 Audience Groups  Group Id  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["audience-groups"],"summary":"Add Group Members","description":"Add candidates to an audience group.","operationId":"add_group_members_api_v1_audience_groups__group_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AudienceGroupMemberAdd"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audience-groups/{group_id}/members/{candidate_id}":{"delete":{"tags":["audience-groups"],"summary":"Remove Group Member","description":"Remove a candidate from an audience group.","operationId":"remove_group_member_api_v1_audience_groups__group_id__members__candidate_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"candidate_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Candidate Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sourcing/build-query":{"post":{"tags":["sourcing"],"summary":"Build Search Query","description":"Build a boolean X-ray query and return the Google Search URL. No API cost.","operationId":"build_search_query_api_v1_sourcing_build_query_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingBuildQueryRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingBuildQueryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sourcing/log-search":{"post":{"tags":["sourcing"],"summary":"Log Search","description":"Log a search to history (called after opening Google). Free, no quota.","operationId":"log_search_api_v1_sourcing_log_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingLogSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sourcing/history":{"get":{"tags":["sourcing"],"summary":"Get History","description":"Get paginated search history.","operationId":"get_history_api_v1_sourcing_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sourcing/add-candidate":{"post":{"tags":["sourcing"],"summary":"Add Candidate From Search","description":"Create a candidate (and optionally an application) from a search result.\n\nX-ray candidates always land in the job's Sourcing stage. If the job's\npipeline has no Sourcing stage, the request is rejected upfront (no\ncandidate is created) so the recruiter can add the stage and retry.","operationId":"add_candidate_from_search_api_v1_sourcing_add_candidate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingAddCandidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sourcing/bulk-import":{"post":{"tags":["sourcing"],"summary":"Bulk Import Profiles","description":"Batch import multiple profile URLs as candidates.","operationId":"bulk_import_profiles_api_v1_sourcing_bulk_import_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingBulkImportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourcingBulkImportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/drip-sequences":{"post":{"tags":["drip-sequences"],"summary":"Create Sequence","description":"Create a drip sequence with optional initial steps.","operationId":"create_sequence_api_v1_drip_sequences_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["drip-sequences"],"summary":"List Sequences","description":"List drip sequences with optional status filter.","operationId":"list_sequences_api_v1_drip_sequences_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_SequenceResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}":{"get":{"tags":["drip-sequences"],"summary":"Get Sequence","description":"Get sequence detail with steps.","operationId":"get_sequence_api_v1_drip_sequences__sequence_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["drip-sequences"],"summary":"Update Sequence","description":"Update sequence metadata. Only allowed when draft or paused.","operationId":"update_sequence_api_v1_drip_sequences__sequence_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["drip-sequences"],"summary":"Delete Sequence","description":"Soft delete a sequence and stop all active enrollments.","operationId":"delete_sequence_api_v1_drip_sequences__sequence_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/activate":{"post":{"tags":["drip-sequences"],"summary":"Activate Sequence","description":"Activate a sequence. Requires at least 1 step.\n\nAny authenticated member can control drip lifecycle (capability\n``campaign:send``, held by Admin/Leader/Member). Tenant-scoped.","operationId":"activate_sequence_api_v1_drip_sequences__sequence_id__activate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/pause":{"post":{"tags":["drip-sequences"],"summary":"Pause Sequence","description":"Pause a sequence and all its active enrollments (capability ``campaign:send``).","operationId":"pause_sequence_api_v1_drip_sequences__sequence_id__pause_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/resume":{"post":{"tags":["drip-sequences"],"summary":"Resume Sequence","description":"Resume a paused sequence and recalculate next_send_at (capability ``campaign:send``).","operationId":"resume_sequence_api_v1_drip_sequences__sequence_id__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/steps":{"post":{"tags":["drip-sequences"],"summary":"Add Step","description":"Add a step to a sequence.","operationId":"add_step_api_v1_drip_sequences__sequence_id__steps_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/steps/reorder":{"put":{"tags":["drip-sequences"],"summary":"Reorder Steps","description":"Reorder steps.","operationId":"reorder_steps_api_v1_drip_sequences__sequence_id__steps_reorder_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepReorderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StepResponse"},"title":"Response Reorder Steps Api V1 Drip Sequences  Sequence Id  Steps Reorder Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/steps/{step_id}":{"put":{"tags":["drip-sequences"],"summary":"Update Step","description":"Update a step.","operationId":"update_step_api_v1_drip_sequences__sequence_id__steps__step_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"step_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Step Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["drip-sequences"],"summary":"Delete Step","description":"Soft delete a step and reorder remaining.","operationId":"delete_step_api_v1_drip_sequences__sequence_id__steps__step_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"step_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Step Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/enroll":{"post":{"tags":["drip-sequences"],"summary":"Enroll","description":"Manually enroll candidates into a sequence.","operationId":"enroll_api_v1_drip_sequences__sequence_id__enroll_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollResultResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/enrollments":{"get":{"tags":["drip-sequences"],"summary":"List Enrollments","description":"List enrollments for a sequence.","operationId":"list_enrollments_api_v1_drip_sequences__sequence_id__enrollments_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_EnrollmentResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/enrollments/{enrollment_id}/pause":{"post":{"tags":["drip-sequences"],"summary":"Pause Single Enrollment","description":"Pause an individual enrollment.","operationId":"pause_single_enrollment_api_v1_drip_sequences__sequence_id__enrollments__enrollment_id__pause_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"enrollment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Enrollment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/enrollments/{enrollment_id}/resume":{"post":{"tags":["drip-sequences"],"summary":"Resume Single Enrollment","description":"Resume a paused enrollment.","operationId":"resume_single_enrollment_api_v1_drip_sequences__sequence_id__enrollments__enrollment_id__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"enrollment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Enrollment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/enrollments/{enrollment_id}/stop":{"post":{"tags":["drip-sequences"],"summary":"Stop Single Enrollment","description":"Manually stop an enrollment.","operationId":"stop_single_enrollment_api_v1_drip_sequences__sequence_id__enrollments__enrollment_id__stop_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}},{"name":"enrollment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Enrollment Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EnrollmentActionRequest"},{"type":"null"}],"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/drip-sequences/{sequence_id}/stats":{"get":{"tags":["drip-sequences"],"summary":"Get Sequence Stats","description":"Get per-step analytics for a sequence.","operationId":"get_sequence_stats_api_v1_drip_sequences__sequence_id__stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sequence_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Sequence Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StepStatsResponse"},"title":"Response Get Sequence Stats Api V1 Drip Sequences  Sequence Id  Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts":{"post":{"tags":["blog"],"summary":"Create Post","description":"Create a blog post (draft). ``published_at`` is NOT set here (sentinel).","operationId":"create_post_api_v1_blog_posts_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["blog"],"summary":"List Posts","description":"List the tenant's non-deleted posts (published first, newest first).","operationId":"list_posts_api_v1_blog_posts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BlogPostListResponse"},"title":"Response List Posts Api V1 Blog Posts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{post_id}":{"get":{"tags":["blog"],"summary":"Get Post","description":"Get one post (with tags + author name).","operationId":"get_post_api_v1_blog_posts__post_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["blog"],"summary":"Update Post","description":"Partial update (serves editor autosave).\n\nSanitizes HTML when present. Does NOT change ``published_at`` or ``status``:\nthe publish lifecycle is owned exclusively by /publish + /unpublish so that\n``status=published`` can never be set without stamping ``published_at`` (the\nbucket-3 sentinel). ``visibility`` IS patchable here.","operationId":"update_post_api_v1_blog_posts__post_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["blog"],"summary":"Delete Post","description":"Soft-delete a post (``is_deleted=True`` + ``deleted_at``).","operationId":"delete_post_api_v1_blog_posts__post_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{post_id}/publish":{"post":{"tags":["blog"],"summary":"Publish Post","description":"Publish now (→ newsletter send job in the SAME tx; the worker sends\nafter commit) or park as scheduled (the scheduled_blogs cron creates the\nsend when the post goes live — spec §3.6). ``published_at`` is stamped\nonly on the first publish (bucket-3 sentinel).\n\nThe list page publishes without deciding anything about the newsletter. Such\na call NEVER creates a send and NEVER mutates the ``newsletter_id`` toggle —\nthat page has no confirmation dialog / recipient count, so it can't be read\nas consent to a real send (spec §7c). The VALUE decides, not the presence of\na body: ``send_newsletter=True`` creates a send now (or lets the cron send it\non schedule); ``send_newsletter=False`` on a scheduled post clears\n``newsletter_id``; ``None`` (absent field OR absent body) leaves it alone.\n\nReading \"no body\" as \"opted out\" is what broke A1: the browser client always\nserialised ``{}``, so every plain publish looked explicit.","operationId":"publish_post_api_v1_blog_posts__post_id__publish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PublishRequest"},{"type":"null"}],"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{post_id}/send-test":{"post":{"tags":["blog"],"summary":"Send Test Post","description":"Email the rendered newsletter to one address; writes no recipient row.","operationId":"send_test_post_api_v1_blog_posts__post_id__send_test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{post_id}/unpublish":{"post":{"tags":["blog"],"summary":"Unpublish Post","description":"Revert a post to draft. ``published_at`` is left untouched (sentinel).","operationId":"unpublish_post_api_v1_blog_posts__post_id__unpublish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/tags":{"get":{"tags":["blog"],"summary":"List Tags","description":"List the tenant's non-deleted tags (alphabetical).","operationId":"list_tags_api_v1_blog_tags_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BlogTagResponse"},"type":"array","title":"Response List Tags Api V1 Blog Tags Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["blog"],"summary":"Create Tag","description":"Create a tag (slug auto-derived from name if omitted; unique per tenant).","operationId":"create_tag_api_v1_blog_tags_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogTagCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlogTagResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/newsletters/":{"get":{"tags":["newsletters"],"summary":"List Newsletters","operationId":"list_newsletters_api_v1_newsletters__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NewsletterResponse"},"type":"array","title":"Response List Newsletters Api V1 Newsletters  Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/newsletters/{newsletter_id}":{"patch":{"tags":["newsletters"],"summary":"Update Newsletter","operationId":"update_newsletter_api_v1_newsletters__newsletter_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"newsletter_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Newsletter Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSettingsUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/{newsletter_id}/recipient-count":{"get":{"tags":["newsletters"],"summary":"Recipient Count","operationId":"recipient_count_api_v1_newsletters__newsletter_id__recipient_count_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"newsletter_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Newsletter Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipientCountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/subscribers":{"get":{"tags":["newsletters"],"summary":"List Subscribers","operationId":"list_subscribers_api_v1_newsletters_subscribers_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["newsletters"],"summary":"Create Subscriber","operationId":"create_subscriber_api_v1_newsletters_subscribers_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberAdminCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/subscribers/import":{"post":{"tags":["newsletters"],"summary":"Import Subscribers","description":"CSV with an ``email`` column (+ optional ``name``); header optional\n(then col 0 = email, col 1 = name). BOM tolerated. Existing addresses are\nskipped untouched (an unsubscribed person is NOT re-subscribed by import).","operationId":"import_subscribers_api_v1_newsletters_subscribers_import_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_subscribers_api_v1_newsletters_subscribers_import_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/newsletters/subscribers/export.csv":{"get":{"tags":["newsletters"],"summary":"Export Subscribers","operationId":"export_subscribers_api_v1_newsletters_subscribers_export_csv_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/newsletters/subscribers/{subscriber_id}":{"patch":{"tags":["newsletters"],"summary":"Update Subscriber","operationId":"update_subscriber_api_v1_newsletters_subscribers__subscriber_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"subscriber_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscriber Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberAdminUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["newsletters"],"summary":"Delete Subscriber","operationId":"delete_subscriber_api_v1_newsletters_subscribers__subscriber_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"subscriber_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscriber Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/subscribers/{subscriber_id}/resend-confirmation":{"post":{"tags":["newsletters"],"summary":"Resend Confirmation","operationId":"resend_confirmation_api_v1_newsletters_subscribers__subscriber_id__resend_confirmation_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"subscriber_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscriber Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/subscribers/{subscriber_id}/restore":{"post":{"tags":["newsletters"],"summary":"Restore Subscriber","description":"Undo a soft delete — the deliberate half of the 409 from ``create``.\n\nRe-enrolls into the default newsletter ONLY for someone whose status is\nstill ``subscribed``: ``delete`` marks every membership unsubscribed, so\nwithout this an admin would restore a row that silently receives nothing.\nSomeone who had opted out stays opted out — restoring a row is not consent.","operationId":"restore_subscriber_api_v1_newsletters_subscribers__subscriber_id__restore_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"subscriber_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscriber Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/sends":{"get":{"tags":["newsletters"],"summary":"List Sends","operationId":"list_sends_api_v1_newsletters_sends_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NewsletterSendListResponse"},"title":"Response List Sends Api V1 Newsletters Sends Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/sends/{send_id}":{"get":{"tags":["newsletters"],"summary":"Get Send","operationId":"get_send_api_v1_newsletters_sends__send_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"send_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Send Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSendDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/newsletters/sends/{send_id}/retry-failed":{"post":{"tags":["newsletters"],"summary":"Retry Failed Send","operationId":"retry_failed_send_api_v1_newsletters_sends__send_id__retry_failed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"send_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Send Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health Check","description":"Health check endpoint with DB connectivity verification.","operationId":"health_check_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"head":{"summary":"Health Check","description":"Health check endpoint with DB connectivity verification.","operationId":"health_check_health_head","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/t/o/{log_id}.png":{"get":{"summary":"Tracking Pixel","description":"Public tracking pixel for email open tracking. No auth required.","operationId":"tracking_pixel_t_o__log_id__png_get","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/t/o/n/{recipient_id}.png":{"get":{"summary":"Newsletter Tracking Pixel","description":"Open pixel for newsletter recipients (self-hosted; Resend tracking is off).","operationId":"newsletter_tracking_pixel_t_o_n__recipient_id__png_get","parameters":[{"name":"recipient_id","in":"path","required":true,"schema":{"type":"string","title":"Recipient Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/t/f/{recipient_id}/{score}":{"get":{"summary":"Newsletter Feedback","description":"Một phiếu 👍/👎 cuối bản tin. Cùng khuôn ký HMAC với /t/c.","operationId":"newsletter_feedback_t_f__recipient_id___score__get","parameters":[{"name":"recipient_id","in":"path","required":true,"schema":{"type":"string","title":"Recipient Id"}},{"name":"score","in":"path","required":true,"schema":{"type":"integer","title":"Score"}},{"name":"s","in":"query","required":true,"schema":{"type":"string","title":"S"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/t/c/{recipient_id}/{idx}":{"get":{"summary":"Newsletter Click Redirect","description":"Click redirect: verify HMAC, stamp click, 302 to the original link.","operationId":"newsletter_click_redirect_t_c__recipient_id___idx__get","parameters":[{"name":"recipient_id","in":"path","required":true,"schema":{"type":"string","title":"Recipient Id"}},{"name":"idx","in":"path","required":true,"schema":{"type":"integer","title":"Idx"}},{"name":"u","in":"query","required":true,"schema":{"type":"string","title":"U"}},{"name":"s","in":"query","required":true,"schema":{"type":"string","title":"S"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActionAuditLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name"},"user_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Email"},"client_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Ip"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"method":{"type":"string","title":"Method"},"path":{"type":"string","title":"Path"},"action":{"type":"string","title":"Action"},"target_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Type"},"target_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Id"},"summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Summary"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id"},"email_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Status"}},"type":"object","required":["id","created_at","method","path","action"],"title":"ActionAuditLogResponse","description":"One audited action — \"who did this, from where\".\n\nReturned by GET /audit/actions (tenant-admin-only). The actor's name/email\nare resolved server-side so the settings table reads without a second\nlookup; they are None when the user was since deleted (FK SET NULL)."},"ActionsSummary":{"properties":{"interviews_today":{"type":"integer","title":"Interviews Today","default":0},"candidates_to_review":{"type":"integer","title":"Candidates To Review","default":0},"stale_count":{"type":"integer","title":"Stale Count","default":0},"pending_hire_confirmations":{"type":"integer","title":"Pending Hire Confirmations","default":0}},"type":"object","title":"ActionsSummary"},"AdditionalQuestionInput":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"question_text":{"type":"string","maxLength":200,"minLength":1,"title":"Question Text"},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true},"is_required":{"type":"boolean","title":"Is Required","default":false},"sort_order":{"type":"integer","title":"Sort Order","default":0}},"type":"object","required":["question_text"],"title":"AdditionalQuestionInput","description":"One item in the admin bulk-update payload."},"AdditionalQuestionPublicResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"question_text":{"type":"string","title":"Question Text"},"is_required":{"type":"boolean","title":"Is Required"},"sort_order":{"type":"integer","title":"Sort Order"}},"type":"object","required":["id","question_text","is_required","sort_order"],"title":"AdditionalQuestionPublicResponse","description":"Public (candidate-facing) view — only enabled questions surface here."},"AdditionalQuestionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"question_text":{"type":"string","title":"Question Text"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_required":{"type":"boolean","title":"Is Required"},"sort_order":{"type":"integer","title":"Sort Order"}},"type":"object","required":["id","question_text","is_enabled","is_required","sort_order"],"title":"AdditionalQuestionResponse","description":"Admin view of a single question."},"AdditionalQuestionsBulkUpdate":{"properties":{"questions":{"items":{"$ref":"#/components/schemas/AdditionalQuestionInput"},"type":"array","title":"Questions"}},"type":"object","title":"AdditionalQuestionsBulkUpdate","description":"Bulk replace-all payload for a tenant's additional questions."},"ApiKeyCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Label shown in Settings, e.g. \"Power BI\""},"expires_in_days":{"anyOf":[{"type":"integer","enum":[30,90,365]},{"type":"null"}],"title":"Expires In Days","description":"30, 90 or 365 days; null = never expires","default":365}},"type":"object","required":["name"],"title":"ApiKeyCreate"},"ApiKeyCreatedResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"key_prefix":{"type":"string","title":"Key Prefix"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"key":{"type":"string","title":"Key","description":"The full key. Shown ONLY in this response — store it now; it cannot be retrieved again."}},"type":"object","required":["id","name","key_prefix","expires_at","created_at","key"],"title":"ApiKeyCreatedResponse"},"ApiKeyItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"key_prefix":{"type":"string","title":"Key Prefix"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"status":{"type":"string","enum":["active","expired","revoked"],"title":"Status"}},"type":"object","required":["id","name","key_prefix","created_by_name","last_used_at","expires_at","revoked_at","created_at","status"],"title":"ApiKeyItem"},"ApiKeyListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ApiKeyItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"ApiKeyListResponse"},"ApplicantStatus":{"type":"string","enum":["active","rejected","hired","removed"],"title":"ApplicantStatus","description":"Whether the applicant is still actively being processed."},"ApplicationCreate":{"properties":{"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"initial_stage":{"anyOf":[{"$ref":"#/components/schemas/ApplicationStage"},{"type":"null"}]},"initial_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Initial Stage Id"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source Detail"}},"type":"object","required":["candidate_id","job_id"],"title":"ApplicationCreate","description":"Schema for creating an application (linking candidate to job)."},"ApplicationFormConfigBulkUpdate":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/ApplicationFormConfigUpdateItem"},"type":"array","title":"Fields"}},"type":"object","required":["fields"],"title":"ApplicationFormConfigBulkUpdate","description":"Bulk update request for all form fields."},"ApplicationFormConfigPublicResponse":{"properties":{"field_key":{"type":"string","title":"Field Key"},"label":{"type":"string","title":"Label"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_required":{"type":"boolean","title":"Is Required"},"sort_order":{"type":"integer","title":"Sort Order"},"is_locked":{"type":"boolean","title":"Is Locked","default":false},"field_type":{"type":"string","title":"Field Type","default":"text"},"step":{"type":"integer","title":"Step","default":0},"step_label":{"type":"string","title":"Step Label","default":"Personal Info"},"placeholder":{"type":"string","title":"Placeholder","default":""},"options":{"items":{"$ref":"#/components/schemas/FieldOptionSchema"},"type":"array","title":"Options","default":[]},"options_i18n_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Options I18N Key"},"validation":{"anyOf":[{"$ref":"#/components/schemas/FieldValidationSchema"},{"type":"null"}]},"full_width":{"type":"boolean","title":"Full Width","default":false}},"type":"object","required":["field_key","label","is_enabled","is_required","sort_order"],"title":"ApplicationFormConfigPublicResponse","description":"Enriched form field config for the public application form.\n\nSuperset of ApplicationFormConfigResponse — includes rendering metadata\nfrom the registry so the frontend doesn't need hardcoded field definitions."},"ApplicationFormConfigResponse":{"properties":{"field_key":{"type":"string","title":"Field Key"},"label":{"type":"string","title":"Label"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_required":{"type":"boolean","title":"Is Required"},"sort_order":{"type":"integer","title":"Sort Order"},"is_locked":{"type":"boolean","title":"Is Locked","default":false}},"type":"object","required":["field_key","label","is_enabled","is_required","sort_order"],"title":"ApplicationFormConfigResponse","description":"Single form field config (used by admin endpoints)."},"ApplicationFormConfigUpdateItem":{"properties":{"field_key":{"type":"string","title":"Field Key"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_required":{"type":"boolean","title":"Is Required"},"sort_order":{"type":"integer","title":"Sort Order"}},"type":"object","required":["field_key","is_enabled","is_required","sort_order"],"title":"ApplicationFormConfigUpdateItem","description":"Single field update within bulk update."},"ApplicationListItem":{"properties":{"application_id":{"type":"string","title":"Application Id"},"candidate_id":{"type":"string","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"recruiter_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recruiter Name"},"stage":{"type":"string","title":"Stage"},"status":{"type":"string","title":"Status"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"effective_entry_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Effective Entry Date"},"applied_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Applied Date"},"hired_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hired Date"},"rejected_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Rejected Date"}},"type":"object","required":["application_id","candidate_id","candidate_name","job_title","stage","status"],"title":"ApplicationListItem","description":"A single application row backing a drilled-into report number.\n\nColumn-only (no relationships) so it is safe to serialize on the async\nsession without risking MissingGreenlet. ``source`` is the RAW\nCandidate.source value (no source-taxonomy grouping at this layer)."},"ApplicationListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ApplicationListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"ApplicationListResponse","description":"Paginated application drill-down response."},"ApplicationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"stage":{"$ref":"#/components/schemas/ApplicationStage"},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"stage_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Stage Updated At"},"status":{"type":"string","title":"Status","default":"active"},"applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied Date"},"hired_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Hired Date"},"rejected_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Rejected Date"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"rejection_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason Code"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"assigned_recruiter":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Recruiter"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"candidate_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Message"},"additional_answers":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Additional Answers"}},"type":"object","required":["id","tenant_id","candidate_id","job_id","stage","stage_updated_at","applied_date","hired_date","rejected_date","rejection_reason","assigned_recruiter","created_at","updated_at"],"title":"ApplicationResponse","description":"Full response schema for an application."},"ApplicationStage":{"type":"string","enum":["sourced","applied","screening","hm_review","test","interview_1","interview_2","offer","hired","rejected"],"title":"ApplicationStage","description":"Legacy pipeline stages for an application (kept for dual-write compat)."},"ApplicationTrend":{"properties":{"week_start":{"type":"string","format":"date","title":"Week Start"},"applications":{"type":"integer","title":"Applications"},"hires":{"type":"integer","title":"Hires"}},"type":"object","required":["week_start","applications","hires"],"title":"ApplicationTrend","description":"Weekly application volume data point."},"ApplicationUpdate":{"properties":{"assigned_recruiter":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Recruiter"},"is_new":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is New"}},"type":"object","title":"ApplicationUpdate","description":"Schema for updating application details."},"ApplicationWithCandidateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"stage":{"$ref":"#/components/schemas/ApplicationStage"},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"stage_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Stage Updated At"},"status":{"type":"string","title":"Status","default":"active"},"applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied Date"},"hired_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Hired Date"},"rejected_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Rejected Date"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"rejection_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason Code"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"assigned_recruiter":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Recruiter"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"},"candidate_code":{"type":"string","title":"Candidate Code"},"candidate_location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Location Display"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Code"},"pipeline_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pipeline Template Id"},"is_new":{"type":"boolean","title":"Is New","default":false},"hm_reviews":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hm Reviews"},"ai_matching_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ai Matching Score"},"matching_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matching Status"},"has_pending_cv":{"type":"boolean","title":"Has Pending Cv","default":false},"candidate_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Message"},"latest_offer_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Offer Status"}},"type":"object","required":["id","tenant_id","candidate_id","job_id","stage","stage_updated_at","applied_date","hired_date","rejected_date","rejection_reason","assigned_recruiter","created_at","updated_at","candidate_name","candidate_code"],"title":"ApplicationWithCandidateResponse","description":"Application response with candidate info (for job pipeline views)."},"ApplicationWithJobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"stage":{"$ref":"#/components/schemas/ApplicationStage"},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"stage_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Stage Updated At"},"status":{"type":"string","title":"Status","default":"active"},"applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied Date"},"hired_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Hired Date"},"rejected_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Rejected Date"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"rejection_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason Code"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"assigned_recruiter":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Recruiter"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_new":{"type":"boolean","title":"Is New","default":false},"job_title":{"type":"string","title":"Job Title"},"job_code":{"type":"string","title":"Job Code"},"job_is_deleted":{"type":"boolean","title":"Job Is Deleted","default":false},"candidate_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Message"},"additional_answers":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Additional Answers"},"latest_offer_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Offer Status"}},"type":"object","required":["id","tenant_id","candidate_id","job_id","stage","stage_updated_at","applied_date","hired_date","rejected_date","rejection_reason","assigned_recruiter","created_at","updated_at","job_title","job_code"],"title":"ApplicationWithJobResponse","description":"Application response with job info (for candidate detail views)."},"AppliedJobInfo":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_title":{"type":"string","title":"Job Title"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","required":["application_id","job_id","job_title"],"title":"AppliedJobInfo","description":"Minimal job info for the applied jobs column."},"ApplyRequest":{"properties":{"selectors":{"items":{"$ref":"#/components/schemas/SourceSelector"},"type":"array","title":"Selectors"},"target":{"$ref":"#/components/schemas/SourceTarget"},"operation":{"type":"string","title":"Operation"},"description":{"type":"string","title":"Description"},"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","required":["selectors","target","operation","description"],"title":"ApplyRequest","description":"Request body for POST /source-management/apply."},"ApplyResponse":{"properties":{"affected_count":{"type":"integer","title":"Affected Count"},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"dry_run":{"type":"boolean","title":"Dry Run"}},"type":"object","required":["affected_count","dry_run"],"title":"ApplyResponse","description":"Response from POST /source-management/apply."},"AssetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"page_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Page Id"},"asset_type":{"$ref":"#/components/schemas/AssetType"},"file_name":{"type":"string","title":"File Name"},"file_url":{"type":"string","title":"File Url"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"File Size"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"alt_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alt Text"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","tenant_id","page_id","asset_type","file_name","file_url","thumbnail_url","file_size","mime_type","width","height","alt_text","created_at"],"title":"AssetResponse","description":"Full asset response."},"AssetType":{"type":"string","enum":["image","video","document"],"title":"AssetType","description":"Types of uploadable assets."},"AssetUploadResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"file_name":{"type":"string","title":"File Name"},"file_url":{"type":"string","title":"File Url"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"asset_type":{"$ref":"#/components/schemas/AssetType"},"file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"File Size"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"}},"type":"object","required":["id","file_name","file_url","thumbnail_url","asset_type","file_size","mime_type","width","height"],"title":"AssetUploadResponse","description":"Response after uploading an asset."},"AudienceFilterPreview":{"properties":{"filter_criteria":{"additionalProperties":true,"type":"object","title":"Filter Criteria"},"limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Limit","default":10}},"type":"object","required":["filter_criteria"],"title":"AudienceFilterPreview","description":"Schema for previewing filter results."},"AudienceGroupCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"filter_criteria":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Criteria"},"auto_add":{"type":"boolean","title":"Auto Add","default":false},"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Candidate Ids"}},"type":"object","required":["name"],"title":"AudienceGroupCreate","description":"Schema for creating an audience group."},"AudienceGroupListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"auto_add":{"type":"boolean","title":"Auto Add"},"candidate_count":{"type":"integer","title":"Candidate Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"}},"type":"object","required":["id","name","auto_add","candidate_count","created_at"],"title":"AudienceGroupListResponse","description":"Lightweight group list item."},"AudienceGroupMemberAdd":{"properties":{"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Candidate Ids"}},"type":"object","required":["candidate_ids"],"title":"AudienceGroupMemberAdd","description":"Schema for adding members to a group."},"AudienceGroupMemberResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"group_id":{"type":"string","format":"uuid","title":"Group Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"added_manually":{"type":"boolean","title":"Added Manually"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"}},"type":"object","required":["id","group_id","candidate_id","added_manually","created_at"],"title":"AudienceGroupMemberResponse","description":"Response schema for a group member."},"AudienceGroupResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"filter_criteria":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Criteria"},"auto_add":{"type":"boolean","title":"Auto Add"},"candidate_count":{"type":"integer","title":"Candidate Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"}},"type":"object","required":["id","tenant_id","name","auto_add","candidate_count","created_at","updated_at"],"title":"AudienceGroupResponse","description":"Response schema for an audience group."},"AudienceGroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"filter_criteria":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Criteria"},"auto_add":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Add"}},"type":"object","title":"AudienceGroupUpdate","description":"Schema for updating an audience group."},"AuthUrlResponse":{"properties":{"auth_url":{"type":"string","title":"Auth Url"}},"type":"object","required":["auth_url"],"title":"AuthUrlResponse"},"AutomationRemindersResponse":{"properties":{"interview_candidate":{"type":"boolean","title":"Interview Candidate"},"interview_interviewer":{"type":"boolean","title":"Interview Interviewer"},"hm_review":{"type":"boolean","title":"Hm Review"},"offer_expiring":{"type":"boolean","title":"Offer Expiring"},"interview_feedback":{"type":"boolean","title":"Interview Feedback"}},"type":"object","required":["interview_candidate","interview_interviewer","hm_review","offer_expiring","interview_feedback"],"title":"AutomationRemindersResponse"},"AutomationRemindersUpdate":{"properties":{"interview_candidate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Interview Candidate"},"interview_interviewer":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Interview Interviewer"},"hm_review":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hm Review"},"offer_expiring":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Offer Expiring"},"interview_feedback":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Interview Feedback"}},"type":"object","title":"AutomationRemindersUpdate"},"BatchCandidateEntry":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"note_to_reviewer":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Note To Reviewer"},"shared_info":{"anyOf":[{"$ref":"#/components/schemas/HMReviewSharedInfo"},{"type":"null"}]}},"type":"object","required":["application_id"],"title":"BatchCandidateEntry","description":"One candidate in a batch HM review request."},"BatchDecisionSubmit":{"properties":{"decisions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Decisions"}},"type":"object","required":["decisions"],"title":"BatchDecisionSubmit","description":"Submit all decisions for a batch review."},"BatchDraftSave":{"properties":{"decisions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Decisions"}},"type":"object","required":["decisions"],"title":"BatchDraftSave","description":"Save draft decisions for a batch review."},"BatchHMReviewRequestCreate":{"properties":{"candidates":{"items":{"$ref":"#/components/schemas/BatchCandidateEntry"},"type":"array","maxItems":50,"minItems":1,"title":"Candidates"},"reviewers":{"items":{"$ref":"#/components/schemas/ReviewerEntry"},"type":"array","maxItems":20,"minItems":1,"title":"Reviewers"},"assignments":{"anyOf":[{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Assignments"},"note_to_reviewers":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Note To Reviewers"},"deadline_days":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Deadline Days","default":3},"send_email":{"type":"boolean","title":"Send Email","default":true},"move_to_hm_review_stage":{"type":"boolean","title":"Move To Hm Review Stage","default":false}},"type":"object","required":["candidates","reviewers"],"title":"BatchHMReviewRequestCreate","description":"Create a batch HM review — multiple candidates × multiple reviewers."},"BatchHMReviewRequestResponse":{"properties":{"batch_ids":{"additionalProperties":{"type":"string"},"type":"object","title":"Batch Ids"},"evaluations_created":{"type":"integer","title":"Evaluations Created"},"reviewers_count":{"type":"integer","title":"Reviewers Count"},"candidates_count":{"type":"integer","title":"Candidates Count"}},"type":"object","required":["batch_ids","evaluations_created","reviewers_count","candidates_count"],"title":"BatchHMReviewRequestResponse","description":"Response after creating a batch HM review."},"BatchUploadFileResult":{"properties":{"filename":{"type":"string","title":"Filename"},"candidate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Candidate Id"},"parse_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parse Job Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["filename"],"title":"BatchUploadFileResult","description":"Per-file result returned by POST /candidates/batch-upload."},"BatchUploadFileStatus":{"properties":{"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"filename":{"type":"string","title":"Filename"},"status":{"type":"string","title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"attempts":{"type":"integer","title":"Attempts","default":0},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"duplicate_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Duplicate Of Id"},"duplicate_of_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duplicate Of Name"},"duplicate_of_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duplicate Of Code"}},"type":"object","required":["candidate_id","filename","status"],"title":"BatchUploadFileStatus","description":"Per-file status returned by GET /candidates/batch-upload/{batch_id}."},"BatchUploadResponse":{"properties":{"batch_id":{"type":"string","format":"uuid","title":"Batch Id"},"files":{"items":{"$ref":"#/components/schemas/BatchUploadFileResult"},"type":"array","title":"Files"}},"type":"object","required":["batch_id","files"],"title":"BatchUploadResponse","description":"Response from POST /candidates/batch-upload."},"BatchUploadStatusResponse":{"properties":{"batch_id":{"type":"string","format":"uuid","title":"Batch Id"},"complete":{"type":"boolean","title":"Complete"},"summary":{"$ref":"#/components/schemas/BatchUploadSummary"},"files":{"items":{"$ref":"#/components/schemas/BatchUploadFileStatus"},"type":"array","title":"Files"}},"type":"object","required":["batch_id","complete","summary","files"],"title":"BatchUploadStatusResponse","description":"Response from GET /candidates/batch-upload/{batch_id}."},"BatchUploadSummary":{"properties":{"added":{"type":"integer","title":"Added","default":0},"empty":{"type":"integer","title":"Empty","default":0},"failed":{"type":"integer","title":"Failed","default":0},"pending":{"type":"integer","title":"Pending","default":0},"duplicates":{"type":"integer","title":"Duplicates","default":0}},"type":"object","title":"BatchUploadSummary","description":"Aggregate counters for a batch."},"BlacklistRequest":{"properties":{"is_blacklisted":{"type":"boolean","title":"Is Blacklisted"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["is_blacklisted"],"title":"BlacklistRequest","description":"Schema for toggling candidate blacklist status."},"BlogPostCreate":{"properties":{"title":{"type":"string","maxLength":500,"title":"Title"},"slug":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Slug"},"content_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content Json"},"content_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Html"},"email_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Html"},"plaintext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plaintext"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"feature_image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Feature Image Url"},"visibility":{"$ref":"#/components/schemas/BlogVisibility","default":"public"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"meta":{"anyOf":[{"$ref":"#/components/schemas/BlogPostMeta"},{"type":"null"}]},"newsletter_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Newsletter Id"},"email_only":{"type":"boolean","title":"Email Only","default":false},"locale":{"type":"string","maxLength":10,"title":"Locale","default":"vi"},"tag_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Tag Ids"}},"type":"object","required":["title"],"title":"BlogPostCreate","description":"Schema for creating a blog post.\n\n``content_html`` / ``email_html`` arrive from the FE (D3) and MUST be\nsanitized server-side before persistence (CQ#2) — Phase 1 concern."},"BlogPostListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"feature_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feature Image Url"},"status":{"type":"string","title":"Status"},"visibility":{"type":"string","title":"Visibility"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"locale":{"type":"string","title":"Locale"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","slug","title","status","visibility","locale","created_at"],"title":"BlogPostListResponse","description":"Lightweight blog post list item (no heavy HTML payload)."},"BlogPostMeta":{"properties":{"meta_title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Meta Title"},"meta_description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Meta Description"},"og_image":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Og Image"}},"type":"object","title":"BlogPostMeta","description":"SEO metadata for a blog post (rendered into ``<head>``).\n\nBounded + scheme-validated to block garbage and XSS via ``meta_title`` /\n``og_image`` when the FE renders these into the document head."},"BlogPostResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"content_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content Json"},"content_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Html"},"email_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Html"},"plaintext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plaintext"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"feature_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feature Image Url"},"status":{"type":"string","title":"Status"},"visibility":{"type":"string","title":"Visibility"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"author_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Author Id"},"meta":{"anyOf":[{"$ref":"#/components/schemas/BlogPostMeta"},{"type":"null"}]},"newsletter_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Newsletter Id"},"email_only":{"type":"boolean","title":"Email Only"},"locale":{"type":"string","title":"Locale"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"tags":{"items":{"$ref":"#/components/schemas/BlogTagResponse"},"type":"array","title":"Tags"},"latest_send":{"anyOf":[{"$ref":"#/components/schemas/NewsletterSendSummary"},{"type":"null"}]}},"type":"object","required":["id","tenant_id","slug","title","status","visibility","email_only","locale","created_at","updated_at"],"title":"BlogPostResponse","description":"Full response schema for a blog post."},"BlogPostStatus":{"type":"string","enum":["draft","scheduled","published"],"title":"BlogPostStatus","description":"Publication status of a blog post."},"BlogPostUpdate":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Title"},"slug":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Slug"},"content_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content Json"},"content_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Html"},"email_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Html"},"plaintext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plaintext"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"feature_image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Feature Image Url"},"status":{"anyOf":[{"$ref":"#/components/schemas/BlogPostStatus"},{"type":"null"}]},"visibility":{"anyOf":[{"$ref":"#/components/schemas/BlogVisibility"},{"type":"null"}]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"meta":{"anyOf":[{"$ref":"#/components/schemas/BlogPostMeta"},{"type":"null"}]},"newsletter_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Newsletter Id"},"email_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Only"},"locale":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Locale"},"tag_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Tag Ids"}},"type":"object","title":"BlogPostUpdate","description":"Schema for updating a blog post (all fields optional)."},"BlogTagCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"slug":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Slug"}},"type":"object","required":["name"],"title":"BlogTagCreate","description":"Schema for creating a blog tag."},"BlogTagResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","slug","created_at","updated_at"],"title":"BlogTagResponse","description":"Response schema for a blog tag."},"BlogVisibility":{"type":"string","enum":["public","members"],"title":"BlogVisibility","description":"Audience visibility of a blog post."},"Body_batch_upload_cvs_api_v1_candidates_batch_upload_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"},"source":{"type":"string","title":"Source","default":"manual"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"}},"type":"object","required":["files"],"title":"Body_batch_upload_cvs_api_v1_candidates_batch_upload_post"},"Body_import_subscribers_api_v1_newsletters_subscribers_import_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"consent_confirmed":{"type":"boolean","title":"Consent Confirmed","default":false},"dry_run":{"type":"boolean","title":"Dry Run","default":true}},"type":"object","required":["file"],"title":"Body_import_subscribers_api_v1_newsletters_subscribers_import_post"},"Body_parse_cv_preview_api_v1_candidates_parse_cv_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_parse_cv_preview_api_v1_candidates_parse_cv_post"},"Body_parse_job_file_api_v1_jobs_parse_file_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_parse_job_file_api_v1_jobs_parse_file_post"},"Body_pre_parse_cv_api_v1_public_applications_pre_parse_cv_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_pre_parse_cv_api_v1_public_applications_pre_parse_cv_post"},"Body_upload_asset_api_v1_company_pages_assets_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"page_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Id"},"alt_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alt Text"}},"type":"object","required":["file"],"title":"Body_upload_asset_api_v1_company_pages_assets_upload_post"},"Body_upload_attachment_api_v1_candidates__candidate_id__attachments_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"attachment_type":{"type":"string","title":"Attachment Type","default":"document"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["file"],"title":"Body_upload_attachment_api_v1_candidates__candidate_id__attachments_post"},"Body_upload_attachment_api_v1_offers__offer_id__attachments_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_attachment_api_v1_offers__offer_id__attachments_post"},"Body_upload_candidate_cv_api_v1_candidates__candidate_id__upload_cv_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"parsed_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parsed Data","description":"Optional JSON string of CvParseResponse from a prior /parse-cv call in the same session. When provided, the LLM re-parse is skipped (preview parse result is canonical for the same file). Dedup is still enforced against the supplied emails/phones."}},"type":"object","required":["file"],"title":"Body_upload_candidate_cv_api_v1_candidates__candidate_id__upload_cv_post"},"Body_upload_email_attachment_api_v1_emails_attachments_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_email_attachment_api_v1_emails_attachments_upload_post"},"Body_upload_tenant_logo_api_v1_tenants_me_logo_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_tenant_logo_api_v1_tenants_me_logo_post"},"BulkRatingRequest":{"properties":{"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Candidate Ids"},"star_rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Star Rating"}},"type":"object","required":["candidate_ids"],"title":"BulkRatingRequest","description":"Bulk-set rating for multiple candidates."},"BulkRejectRequest":{"properties":{"application_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"minItems":1,"title":"Application Ids"},"reason_code":{"type":"string","maxLength":50,"minLength":1,"title":"Reason Code"},"reason_detail":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Reason Detail"},"reason":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Reason"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"send_email":{"type":"boolean","title":"Send Email","default":true}},"type":"object","required":["application_ids","reason_code"],"title":"BulkRejectRequest","description":"Schema for bulk rejecting multiple applications."},"BulkRejectResponse":{"properties":{"rejected":{"type":"integer","title":"Rejected","default":0},"skipped":{"type":"integer","title":"Skipped","default":0},"errors":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Errors","default":[]}},"type":"object","title":"BulkRejectResponse","description":"Response for bulk reject operation."},"CalendarConnectedResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"calendar_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Email"}},"type":"object","required":["success"],"title":"CalendarConnectedResponse"},"CalendarSettingsResponse":{"properties":{"hide_guest_list":{"type":"boolean","title":"Hide Guest List"}},"type":"object","required":["hide_guest_list"],"title":"CalendarSettingsResponse"},"CalendarSettingsUpdate":{"properties":{"hide_guest_list":{"type":"boolean","title":"Hide Guest List"}},"type":"object","required":["hide_guest_list"],"title":"CalendarSettingsUpdate"},"CalendarStatusResponse":{"properties":{"connected":{"type":"boolean","title":"Connected"},"calendar_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Email"}},"type":"object","required":["connected"],"title":"CalendarStatusResponse"},"CallbackRequest":{"properties":{"code":{"type":"string","title":"Code"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},"type":"object","required":["code"],"title":"CallbackRequest"},"CampaignCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"subject":{"type":"string","maxLength":500,"title":"Subject"},"body":{"type":"string","title":"Body"},"audience_group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Audience Group Id"},"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Candidate Ids"},"send_type":{"type":"string","title":"Send Type","default":"immediate"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"recurrence_rule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Recurrence Rule"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"header_image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Header Image Url"}},"type":"object","required":["name","subject","body"],"title":"CampaignCreate","description":"Schema for creating an email campaign."},"CampaignListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","title":"Status"},"total_recipients":{"type":"integer","title":"Total Recipients"},"sent_count":{"type":"integer","title":"Sent Count"},"opened_count":{"type":"integer","title":"Opened Count"},"bounced_count":{"type":"integer","title":"Bounced Count"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"}},"type":"object","required":["id","name","subject","status","total_recipients","sent_count","opened_count","bounced_count","created_at"],"title":"CampaignListResponse","description":"Lightweight campaign list item."},"CampaignRecipientResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"email_log_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Email Log Id"},"status":{"type":"string","title":"Status"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"opened_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Opened At"},"clicked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Clicked At"},"bounced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Bounced At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"}},"type":"object","required":["id","campaign_id","candidate_id","status"],"title":"CampaignRecipientResponse","description":"Response schema for a campaign recipient."},"CampaignResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"name":{"type":"string","title":"Name"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"status":{"type":"string","title":"Status"},"filter_criteria":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Criteria"},"total_recipients":{"type":"integer","title":"Total Recipients"},"sent_count":{"type":"integer","title":"Sent Count"},"opened_count":{"type":"integer","title":"Opened Count"},"clicked_count":{"type":"integer","title":"Clicked Count"},"bounced_count":{"type":"integer","title":"Bounced Count"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"audience_group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Audience Group Id"},"send_type":{"type":"string","title":"Send Type","default":"immediate"},"recurrence_rule":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Recurrence Rule"},"send_count":{"type":"integer","title":"Send Count","default":0},"next_send_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Send At"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"header_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Header Image Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"},"audience_group_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audience Group Name"}},"type":"object","required":["id","tenant_id","name","subject","body","status","total_recipients","sent_count","opened_count","clicked_count","bounced_count","created_at","updated_at"],"title":"CampaignResponse","description":"Response schema for an email campaign."},"CampaignTemplateCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"category":{"type":"string","maxLength":50,"title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"subject":{"type":"string","maxLength":500,"title":"Subject"},"header_image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Header Image Url"},"body":{"type":"string","title":"Body"}},"type":"object","required":["name","category","subject","body"],"title":"CampaignTemplateCreate","description":"Schema for creating a campaign template."},"CampaignTemplateListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"subject":{"type":"string","title":"Subject"},"header_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Header Image Url"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"is_system":{"type":"boolean","title":"Is System"},"usage_count":{"type":"integer","title":"Usage Count"}},"type":"object","required":["id","name","category","subject","is_system","usage_count"],"title":"CampaignTemplateListResponse","description":"Lightweight template list item."},"CampaignTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tenant Id"},"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"subject":{"type":"string","title":"Subject"},"header_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Header Image Url"},"body":{"type":"string","title":"Body"},"thumbnail_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumbnail Url"},"is_system":{"type":"boolean","title":"Is System"},"usage_count":{"type":"integer","title":"Usage Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","category","subject","body","is_system","usage_count","created_at","updated_at"],"title":"CampaignTemplateResponse","description":"Response schema for a campaign template."},"CampaignTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"category":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Category"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Subject"},"header_image_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Header Image Url"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","title":"CampaignTemplateUpdate","description":"Schema for updating a campaign template."},"CampaignUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","title":"CampaignUpdate","description":"Schema for updating a draft campaign."},"CandidateAccessLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"viewer_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Viewer User Id"},"viewer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Viewer Name"},"owner_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Owner User Id"},"owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Name"},"access_type":{"type":"string","title":"Access Type"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","candidate_id","access_type","created_at"],"title":"CandidateAccessLogResponse","description":"One cross-owner access event (Audit — Visibility not Walls).\n\nReturned by GET /candidates/access-log (admin-only). Names are resolved\nserver-side so the admin dashboard reads without a second lookup."},"CandidateAttachmentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"file_url":{"type":"string","title":"File Url"},"original_filename":{"type":"string","title":"Original Filename"},"file_size_bytes":{"type":"integer","title":"File Size Bytes"},"content_type":{"type":"string","title":"Content Type"},"attachment_type":{"type":"string","title":"Attachment Type"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"uploaded_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Uploaded By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","candidate_id","file_url","original_filename","file_size_bytes","content_type","attachment_type","created_at","updated_at"],"title":"CandidateAttachmentResponse","description":"Response for a single attachment."},"CandidateAttachmentUpdate":{"properties":{"label":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label"},"attachment_type":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Attachment Type"}},"type":"object","title":"CandidateAttachmentUpdate","description":"Update an attachment's metadata."},"CandidateCreate":{"properties":{"full_name":{"type":"string","maxLength":255,"minLength":1,"title":"Full Name"},"email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"gender":{"anyOf":[{"$ref":"#/components/schemas/Gender"},{"type":"null"}]},"communication_channel":{"anyOf":[{"$ref":"#/components/schemas/CommunicationChannel"},{"type":"null"}]},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"available_from_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available From Date"},"country_code":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Country Code","default":"VN"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"willing_to_relocate":{"type":"boolean","title":"Willing To Relocate","default":false},"current_job_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"has_management_experience":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Management Experience"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"education":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Education"},"current_salary":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Current Salary"},"current_salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Current Salary Currency"},"current_salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Current Salary Type","default":"gross"},"current_salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Current Salary Period","default":"monthly"},"expected_salary_min":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Expected Salary Min"},"expected_salary_max":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Expected Salary Max"},"salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Salary Type","default":"gross"},"salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Salary Period","default":"monthly"},"linkedin_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Linkedin Url"},"source":{"type":"string","maxLength":50,"minLength":1,"title":"Source","description":"Source is required"},"source_detail":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source Detail"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"},"cv_raw_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Raw Text"},"cv_raw_blocks":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Raw Blocks"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review","default":false},"star_rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Star Rating"}},"type":"object","required":["full_name","source"],"title":"CandidateCreate","description":"Schema for creating a new candidate."},"CandidateDeletePreviewResponse":{"properties":{"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"application_count":{"type":"integer","title":"Application Count"},"job_count":{"type":"integer","title":"Job Count"}},"type":"object","required":["candidate_id","candidate_name","application_count","job_count"],"title":"CandidateDeletePreviewResponse","description":"Response from GET /candidates/{id}/delete-preview."},"CandidateDuplicateRef":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"}},"type":"object","required":["id","candidate_code","full_name"],"title":"CandidateDuplicateRef","description":"Lightweight reference to the original candidate for the duplicate banner."},"CandidateJourneyResponse":{"properties":{"candidate_context":{"$ref":"#/components/schemas/JourneyCandidateContext"},"summary":{"$ref":"#/components/schemas/JourneySummary"},"applications":{"items":{"$ref":"#/components/schemas/JourneyApplicationGroup"},"type":"array","title":"Applications","default":[]}},"type":"object","required":["candidate_context","summary"],"title":"CandidateJourneyResponse","description":"Response for GET /candidates/{id}/complete-history (journey story)."},"CandidateLinkCreate":{"properties":{"link_type":{"type":"string","maxLength":30,"title":"Link Type"},"url":{"type":"string","maxLength":1000,"minLength":1,"title":"Url"},"label":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label"}},"type":"object","required":["link_type","url"],"title":"CandidateLinkCreate","description":"Create a new link on a candidate profile."},"CandidateLinkResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"link_type":{"type":"string","title":"Link Type"},"url":{"type":"string","title":"Url"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"sort_order":{"type":"integer","title":"Sort Order","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","candidate_id","link_type","url","created_at","updated_at"],"title":"CandidateLinkResponse","description":"Response for a single link."},"CandidateLinkUpdate":{"properties":{"link_type":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Link Type"},"url":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Url"},"label":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label"}},"type":"object","title":"CandidateLinkUpdate","description":"Update a link."},"CandidateListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"},"communication_channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Communication Channel"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"source":{"type":"string","title":"Source"},"star_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Star Rating"},"is_blacklisted":{"type":"boolean","title":"Is Blacklisted"},"is_email_unsubscribed":{"type":"boolean","title":"Is Email Unsubscribed","default":false},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review","default":false},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"has_multiple_cvs":{"type":"boolean","title":"Has Multiple Cvs","default":false},"latest_application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Latest Application Id"},"latest_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Stage"},"latest_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Stage Name"},"latest_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Job Title"},"latest_job_department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Job Department"},"latest_applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Latest Applied Date"},"latest_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Latest Job Id"},"latest_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Latest Stage Id"},"pipeline_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pipeline Template Id"},"duplicate_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Duplicate Of Id"},"latest_offer_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Offer Status"}},"type":"object","required":["id","candidate_code","full_name","phone","current_job_title","current_company","source","is_blacklisted","tags","created_at"],"title":"CandidateListResponse","description":"Lighter response for candidate list views."},"CandidateParseJobInfo":{"properties":{"status":{"type":"string","title":"Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"attempts":{"type":"integer","title":"Attempts","default":0},"max_attempts":{"type":"integer","title":"Max Attempts","default":3}},"type":"object","required":["status"],"title":"CandidateParseJobInfo","description":"Latest cv_parse_job snapshot for a candidate — drives the detail banner\nthat tells the user whether the batch-uploaded CV failed or came back empty."},"CandidateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"},"communication_channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Communication Channel"},"english_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"English Level"},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"available_from_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available From Date"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"country_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Name"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"vn_province_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Name"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"state_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Name"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"willing_to_relocate":{"type":"boolean","title":"Willing To Relocate"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"has_management_experience":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Management Experience"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"education":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Education"},"current_salary":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Salary"},"current_salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Currency"},"current_salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Type"},"current_salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Period"},"expected_salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Salary Min"},"expected_salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"source":{"type":"string","title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"},"cv_raw_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Raw Text"},"cv_raw_blocks":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Raw Blocks"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review"},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"duplicate_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Duplicate Of Id"},"duplicate_of":{"anyOf":[{"$ref":"#/components/schemas/CandidateDuplicateRef"},{"type":"null"}]},"parse_job":{"anyOf":[{"$ref":"#/components/schemas/CandidateParseJobInfo"},{"type":"null"}]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"star_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Star Rating"},"last_edited_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Last Edited By User Id"},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"is_owner":{"type":"boolean","title":"Is Owner","default":false},"is_blacklisted":{"type":"boolean","title":"Is Blacklisted"},"blacklist_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blacklist Reason"},"is_email_unsubscribed":{"type":"boolean","title":"Is Email Unsubscribed"},"email_unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Email Unsubscribed At"},"last_contacted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Contacted At"},"is_anonymized":{"type":"boolean","title":"Is Anonymized","default":false},"anonymized_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Anonymized At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","candidate_code","full_name","phone","willing_to_relocate","current_job_title","current_company","total_experience_years","skills","education","expected_salary_min","expected_salary_max","salary_currency","linkedin_url","source","source_detail","cv_file_url","cv_raw_text","cv_raw_blocks","cv_parsed_data","needs_manual_review","tags","notes","is_blacklisted","blacklist_reason","is_email_unsubscribed","email_unsubscribed_at","last_contacted_at","created_at","updated_at"],"title":"CandidateResponse","description":"Full response schema for a candidate."},"CandidateTagsUpdate":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags"}},"type":"object","required":["tags"],"title":"CandidateTagsUpdate","description":"Schema for updating candidate tags."},"CandidateTalentGroup":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"}},"type":"object","required":["id","name"],"title":"CandidateTalentGroup","description":"A group a given candidate belongs to (for chips on the candidate screen)."},"CandidateUpdate":{"properties":{"full_name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Full Name"},"email":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"gender":{"anyOf":[{"$ref":"#/components/schemas/Gender"},{"type":"null"}]},"communication_channel":{"anyOf":[{"$ref":"#/components/schemas/CommunicationChannel"},{"type":"null"}]},"english_level":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"English Level"},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"available_from_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Available From Date"},"country_code":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Country Code"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"willing_to_relocate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Willing To Relocate"},"current_job_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"has_management_experience":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Management Experience"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"education":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Education"},"current_salary":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Current Salary"},"current_salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Current Salary Currency"},"current_salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Current Salary Type"},"current_salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Current Salary Period"},"expected_salary_min":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Expected Salary Min"},"expected_salary_max":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Expected Salary Max"},"salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Salary Period"},"linkedin_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Linkedin Url"},"source":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source Detail"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"cv_raw_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Raw Text"},"cv_raw_blocks":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Raw Blocks"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"},"needs_manual_review":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Needs Manual Review"},"star_rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Star Rating"}},"type":"object","title":"CandidateUpdate","description":"Schema for updating a candidate."},"CatalogCustomSource":{"properties":{"name":{"type":"string","title":"Name"},"value":{"type":"string","title":"Value"},"parent_source":{"type":"string","title":"Parent Source"}},"type":"object","required":["name","value","parent_source"],"title":"CatalogCustomSource"},"CatalogMember":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"full_name":{"type":"string","title":"Full Name"},"role":{"type":"string","title":"Role"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","full_name","role","is_active"],"title":"CatalogMember"},"CatalogPipelineTemplate":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_default":{"type":"boolean","title":"Is Default"},"stages":{"items":{"$ref":"#/components/schemas/CatalogTemplateStage"},"type":"array","title":"Stages"}},"type":"object","required":["id","name","is_default","stages"],"title":"CatalogPipelineTemplate"},"CatalogRejectionReason":{"properties":{"code":{"type":"string","title":"Code"},"label":{"type":"string","title":"Label"}},"type":"object","required":["code","label"],"title":"CatalogRejectionReason"},"CatalogTemplateStage":{"properties":{"name":{"type":"string","title":"Name"},"stage_type":{"type":"string","title":"Stage Type"},"sort_order":{"type":"integer","title":"Sort Order"},"is_terminal":{"type":"boolean","title":"Is Terminal"}},"type":"object","required":["name","stage_type","sort_order","is_terminal"],"title":"CatalogTemplateStage"},"CityResponse":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"state_id":{"type":"integer","title":"State Id"}},"type":"object","required":["id","name","state_id"],"title":"CityResponse"},"ClassifiedSkills":{"properties":{"must_have":{"items":{"type":"string"},"type":"array","title":"Must Have","default":[]},"nice_to_have":{"items":{"type":"string"},"type":"array","title":"Nice To Have","default":[]},"languages":{"items":{"type":"string"},"type":"array","title":"Languages","default":[]},"certs":{"items":{"type":"string"},"type":"array","title":"Certs","default":[]},"confidence":{"type":"string","enum":["high","fallback"],"title":"Confidence","default":"fallback"}},"type":"object","title":"ClassifiedSkills","description":"Skills classified into must-have / nice-to-have / languages / certs.\n\nPopulated by ``app.services.skill_classifier.classify_skills`` from a\njob's ``required_skills`` list + ``requirements`` text. Pure regex +\nstatic markers, no LLM."},"CombinedStatusResponse":{"properties":{"google":{"$ref":"#/components/schemas/ProviderStatus"},"microsoft":{"$ref":"#/components/schemas/ProviderStatus"},"active_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Provider"}},"type":"object","required":["google","microsoft"],"title":"CombinedStatusResponse"},"CommunicationChannel":{"type":"string","enum":["zalo","messenger","whatsapp","email","linkedin","other"],"title":"CommunicationChannel","description":"Primary communication channel with candidate."},"CompanyPageContentUpdate":{"properties":{"content":{"additionalProperties":true,"type":"object","title":"Content"},"last_client_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Client Update"}},"type":"object","required":["content"],"title":"CompanyPageContentUpdate","description":"Schema for auto-save content updates."},"CompanyPageCreate":{"properties":{"page_type":{"$ref":"#/components/schemas/PageType","default":"custom"},"slug":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z0-9-]+$","title":"Slug"},"title":{"type":"string","maxLength":255,"minLength":1,"title":"Title"},"meta_description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Meta Description"},"content":{"additionalProperties":true,"type":"object","title":"Content"},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings"}},"type":"object","required":["slug","title"],"title":"CompanyPageCreate","description":"Schema for creating a new company page."},"CompanyPageListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"page_code":{"type":"string","title":"Page Code"},"page_type":{"$ref":"#/components/schemas/PageType"},"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"subdomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subdomain"},"status":{"$ref":"#/components/schemas/PageStatus"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","page_code","page_type","slug","title","status","published_at","created_at","updated_at"],"title":"CompanyPageListResponse","description":"Simplified response for page lists."},"CompanyPagePublish":{"properties":{"change_summary":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Change Summary"}},"type":"object","title":"CompanyPagePublish","description":"Schema for publishing a page."},"CompanyPageResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"tenant_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant Code"},"page_code":{"type":"string","title":"Page Code"},"page_type":{"$ref":"#/components/schemas/PageType"},"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"subdomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subdomain"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"og_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Og Image Url"},"content":{"additionalProperties":true,"type":"object","title":"Content"},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings"},"status":{"$ref":"#/components/schemas/PageStatus"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","page_code","page_type","slug","title","meta_description","og_image_url","content","settings","status","published_at","created_by","created_at","updated_at"],"title":"CompanyPageResponse","description":"Response schema for a company page."},"CompanyPageUpdate":{"properties":{"page_type":{"anyOf":[{"$ref":"#/components/schemas/PageType"},{"type":"null"}]},"slug":{"anyOf":[{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z0-9-]+$"},{"type":"null"}],"title":"Slug"},"title":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Title"},"meta_description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Meta Description"},"og_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Og Image Url"},"content":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content"},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings"}},"type":"object","title":"CompanyPageUpdate","description":"Schema for updating a company page."},"ConfirmResponse":{"properties":{"status":{"type":"string","title":"Status"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},"type":"object","required":["status"],"title":"ConfirmResponse","description":"Result of clicking the double-opt-in magic link."},"ConversionRate":{"properties":{"from_stage":{"type":"string","title":"From Stage"},"from_label":{"type":"string","title":"From Label"},"to_stage":{"type":"string","title":"To Stage"},"to_label":{"type":"string","title":"To Label"},"from_count":{"type":"integer","title":"From Count"},"to_count":{"type":"integer","title":"To Count"},"rate":{"type":"number","title":"Rate"}},"type":"object","required":["from_stage","from_label","to_stage","to_label","from_count","to_count","rate"],"title":"ConversionRate","description":"Conversion rate between two adjacent pipeline stages."},"CountryResponse":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"iso2":{"type":"string","title":"Iso2"},"emoji":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Emoji"}},"type":"object","required":["id","name","iso2"],"title":"CountryResponse"},"CriterionInput":{"properties":{"key":{"type":"string","maxLength":50,"minLength":1,"title":"Key"},"label":{"type":"string","maxLength":200,"minLength":1,"title":"Label"},"weight":{"type":"number","maximum":10.0,"minimum":0.1,"title":"Weight","default":1.0},"required":{"type":"boolean","title":"Required","default":false},"rubric":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Rubric","description":"Behavioral anchors per score level, e.g. {'1':'No evidence','5':'Exceptional'}"}},"type":"object","required":["key","label"],"title":"CriterionInput","description":"A single evaluation criterion."},"CriterionScoreInput":{"properties":{"key":{"type":"string","maxLength":50,"minLength":1,"title":"Key"},"label":{"type":"string","maxLength":200,"minLength":1,"title":"Label"},"score":{"type":"integer","maximum":10.0,"minimum":0.0,"title":"Score"},"weight":{"type":"number","maximum":10.0,"minimum":0.1,"title":"Weight","default":1.0},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Note","description":"Evidence or justification for this score"}},"type":"object","required":["key","label","score"],"title":"CriterionScoreInput","description":"A single criterion score from an evaluator."},"CustomSourceCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"parent_source":{"type":"string","maxLength":50,"minLength":1,"title":"Parent Source"},"show_on_career_form":{"type":"boolean","title":"Show On Career Form","default":false}},"type":"object","required":["name","parent_source"],"title":"CustomSourceCreate"},"CvHistoryItem":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"is_primary":{"type":"boolean","title":"Is Primary"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"},"cv_file_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Hash"},"uploaded_via":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Uploaded Via"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"is_pending":{"type":"boolean","title":"Is Pending","default":false},"pending_for_application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pending For Application Id"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"}},"type":"object","required":["is_primary"],"title":"CvHistoryItem","description":"Một CV trong bộ CV đầy đủ của ứng viên (CV chính ∪ candidate_cv_history) — Nhịp 5.\n\n``id`` = id dòng candidate_cv_history (None nếu CV chính chưa từng được archive vào history).\n``is_primary`` = CV này đang là CV chính (candidate.cv_*). CV phụ (is_primary=False) có thể\nbấm \"Đặt làm CV chính\" (cần ``id``). ``job_title`` resolve từ ``job_id`` để hiển thị \"CV cho job X\"."},"CvHistoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CvHistoryItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"CvHistoryListResponse","description":"Bộ CV đầy đủ của một ứng viên: CV chính + mọi CV trong lịch sử (đã dedup, CV chính trước)."},"CvParseResponse":{"properties":{"raw_text":{"type":"string","title":"Raw Text"},"raw_blocks":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Raw Blocks"},"emails":{"items":{"type":"string"},"type":"array","title":"Emails"},"phones":{"items":{"type":"string"},"type":"array","title":"Phones"},"extracted_name":{"type":"string","title":"Extracted Name"},"confidence":{"type":"string","title":"Confidence"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review"},"parse_success":{"type":"boolean","title":"Parse Success"},"parse_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parse Error"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"},"candidate_fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Candidate Fields"}},"type":"object","required":["raw_text","raw_blocks","emails","phones","extracted_name","confidence","needs_manual_review","parse_success"],"title":"CvParseResponse","description":"Response from CV parse-only endpoint."},"CvPendingResolveRequest":{"properties":{"action":{"type":"string","enum":["replace","keep_both","discard"],"title":"Action"}},"type":"object","required":["action"],"title":"CvPendingResolveRequest","description":"HR quyết CV đang chờ đối chiếu (WS4/QĐ-F): replace | keep_both | discard."},"CvPendingResolveResponse":{"properties":{"action":{"type":"string","title":"Action"},"cv_history_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cv History Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"offer_rescore":{"type":"boolean","title":"Offer Rescore","default":false}},"type":"object","required":["action"],"title":"CvPendingResolveResponse"},"CvUploadResponse":{"properties":{"cv_file_url":{"type":"string","title":"Cv File Url"},"cv_original_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv Original Filename"},"cv_raw_text":{"type":"string","title":"Cv Raw Text"},"cv_raw_blocks":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Cv Raw Blocks"},"cv_parsed_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Cv Parsed Data"},"confidence":{"type":"string","title":"Confidence"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review"},"candidate_fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Candidate Fields"}},"type":"object","required":["cv_file_url","cv_raw_text","cv_raw_blocks","confidence","needs_manual_review"],"title":"CvUploadResponse","description":"Response from CV upload endpoint."},"DashboardStats":{"properties":{"jobs_total":{"type":"integer","title":"Jobs Total","default":0},"jobs_open":{"type":"integer","title":"Jobs Open","default":0},"jobs_draft":{"type":"integer","title":"Jobs Draft","default":0},"jobs_closed":{"type":"integer","title":"Jobs Closed","default":0},"jobs_on_hold":{"type":"integer","title":"Jobs On Hold","default":0},"candidates_total":{"type":"integer","title":"Candidates Total","default":0},"candidates_blacklisted":{"type":"integer","title":"Candidates Blacklisted","default":0},"applications_total":{"type":"integer","title":"Applications Total","default":0},"applications_sourced":{"type":"integer","title":"Applications Sourced","default":0},"applications_applied":{"type":"integer","title":"Applications Applied","default":0},"applications_screening":{"type":"integer","title":"Applications Screening","default":0},"applications_interview":{"type":"integer","title":"Applications Interview","default":0},"applications_offer":{"type":"integer","title":"Applications Offer","default":0},"applications_hired":{"type":"integer","title":"Applications Hired","default":0},"applications_rejected":{"type":"integer","title":"Applications Rejected","default":0},"candidates_high_rated":{"type":"integer","title":"Candidates High Rated","default":0},"recent_candidates":{"items":{"$ref":"#/components/schemas/RecentCandidate"},"type":"array","title":"Recent Candidates","default":[]},"recent_applications":{"items":{"$ref":"#/components/schemas/RecentApplication"},"type":"array","title":"Recent Applications","default":[]}},"type":"object","title":"DashboardStats"},"DataApplication":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_code":{"type":"string","title":"Job Code"},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"stage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Type"},"status":{"type":"string","title":"Status"},"applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied Date"},"hired_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Hired Date"},"rejected_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Rejected Date"},"rejection_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason Code"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"assigned_recruiter_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Recruiter Id"},"assigned_recruiter_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned Recruiter Name"},"offer_accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Offer Accepted At"},"is_demo":{"type":"boolean","title":"Is Demo"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"stage_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Stage Updated At"}},"type":"object","required":["id","candidate_id","candidate_code","job_id","job_code","stage_id","stage_name","stage_type","status","applied_date","hired_date","rejected_date","rejection_reason_code","rejection_reason","source","source_detail","assigned_recruiter_id","assigned_recruiter_name","offer_accepted_at","is_demo","created_at","updated_at","stage_updated_at"],"title":"DataApplication"},"DataCandidate":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"skills":{"anyOf":[{},{"type":"null"}],"title":"Skills"},"education":{"anyOf":[{},{"type":"null"}],"title":"Education"},"current_salary":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Salary"},"current_salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Currency"},"current_salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Type"},"current_salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Salary Period"},"expected_salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Salary Min"},"expected_salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"source":{"type":"string","title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"tags":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Tags"},"star_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Star Rating"},"is_blacklisted":{"type":"boolean","title":"Is Blacklisted"},"is_demo":{"type":"boolean","title":"Is Demo"},"is_anonymized":{"type":"boolean","title":"Is Anonymized"},"duplicate_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Duplicate Of Id"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","candidate_code","full_name","email","phone","gender","date_of_birth","location_display","vn_province_code","country_code","current_job_title","current_company","total_experience_years","skills","education","current_salary","current_salary_currency","current_salary_type","current_salary_period","expected_salary_min","expected_salary_max","salary_currency","salary_type","salary_period","source","source_detail","tags","star_rating","is_blacklisted","is_demo","is_anonymized","duplicate_of_id","needs_manual_review","created_at","updated_at"],"title":"DataCandidate"},"DataCatalog":{"properties":{"pipeline_templates":{"items":{"$ref":"#/components/schemas/CatalogPipelineTemplate"},"type":"array","title":"Pipeline Templates"},"custom_sources":{"items":{"$ref":"#/components/schemas/CatalogCustomSource"},"type":"array","title":"Custom Sources"},"rejection_reasons":{"items":{"$ref":"#/components/schemas/CatalogRejectionReason"},"type":"array","title":"Rejection Reasons"},"members":{"items":{"$ref":"#/components/schemas/CatalogMember"},"type":"array","title":"Members"},"departments":{"items":{"type":"string"},"type":"array","title":"Departments"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"type":"object","required":["pipeline_templates","custom_sources","rejection_reasons","members","departments","generated_at"],"title":"DataCatalog"},"DataEvaluation":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"interview_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Interview Id"},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"evaluator_type":{"type":"string","title":"Evaluator Type"},"evaluator_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Evaluator Id"},"evaluator_name":{"type":"string","title":"Evaluator Name"},"overall_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overall Rating"},"rating_scale":{"type":"integer","title":"Rating Scale"},"criteria_scores":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"weighted_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weighted Score"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"evaluation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluation Type"},"evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evaluated At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","application_id","candidate_id","job_id","interview_id","stage_id","evaluator_type","evaluator_id","evaluator_name","overall_rating","rating_scale","criteria_scores","weighted_score","result","evaluation_type","evaluated_at","created_at","updated_at"],"title":"DataEvaluation"},"DataInterview":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"interview_round":{"type":"string","title":"Interview Round"},"round_number":{"type":"integer","title":"Round Number"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"status":{"type":"string","title":"Status"},"result":{"type":"string","title":"Result"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"interviewer_ids":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Interviewer Ids"},"interviewer_names":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Interviewer Names"},"is_self_schedule":{"type":"boolean","title":"Is Self Schedule"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","application_id","candidate_id","job_id","interview_round","round_number","scheduled_at","duration_minutes","location","status","result","rating","interviewer_ids","interviewer_names","is_self_schedule","created_at","updated_at"],"title":"DataInterview"},"DataJob":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"job_code":{"type":"string","title":"Job Code"},"title":{"type":"string","title":"Title"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"employment_type":{"type":"string","title":"Employment Type"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"hire_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hire Type"},"status":{"type":"string","title":"Status"},"published_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published Date"},"closed_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed Date"},"on_hold_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"On Hold Date"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"expected_hire_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expected Hire Date"},"headcount":{"type":"integer","title":"Headcount"},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"recruitment_cost_items":{"items":{},"type":"array","title":"Recruitment Cost Items"},"cost_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Currency"},"pipeline_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pipeline Template Id"},"is_demo":{"type":"boolean","title":"Is Demo"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"pipeline_stages":{"items":{"$ref":"#/components/schemas/DataPipelineStage"},"type":"array","title":"Pipeline Stages"}},"type":"object","required":["id","job_code","title","slug","department","location_display","employment_type","work_setup","hire_type","status","published_date","closed_date","on_hold_date","close_reason","expected_hire_date","headcount","salary_min","salary_max","salary_currency","recruitment_cost_items","cost_currency","pipeline_template_id","is_demo","created_by","created_at","updated_at","pipeline_stages"],"title":"DataJob"},"DataMeta":{"properties":{"from":{"type":"string","format":"date","title":"From","description":"First business day (Asia/Ho_Chi_Minh) of the window actually served"},"to":{"type":"string","format":"date","title":"To","description":"Last business day of the window (inclusive)"},"from_clamped":{"type":"boolean","title":"From Clamped","description":"True when the requested `from` was older than the 18-month limit and was moved forward"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"type":"object","required":["from","to","from_clamped","generated_at"],"title":"DataMeta"},"DataOffer":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"offer_number":{"type":"string","title":"Offer Number"},"version":{"type":"integer","title":"Version"},"status":{"type":"string","title":"Status"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"gross_salary_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gross Salary Amount"},"gross_salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary Currency"},"gross_salary_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary Unit"},"probation_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Period"},"probation_salary_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Probation Salary Amount"},"expiry_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiry Date"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Responded At"},"decline_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Reason Code"},"cancel_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason Code"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","application_id","candidate_id","job_id","offer_number","version","status","job_title","department","start_date","gross_salary_amount","gross_salary_currency","gross_salary_unit","probation_period","probation_salary_amount","expiry_date","sent_at","responded_at","decline_reason_code","cancel_reason_code","created_at","updated_at"],"title":"DataOffer"},"DataPage_DataApplication_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataApplication"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataApplication]"},"DataPage_DataCandidate_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataCandidate"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataCandidate]"},"DataPage_DataEvaluation_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataEvaluation"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataEvaluation]"},"DataPage_DataInterview_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataInterview"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataInterview]"},"DataPage_DataJob_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataJob"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataJob]"},"DataPage_DataOffer_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataOffer"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataOffer]"},"DataPage_DataStageTransition_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DataStageTransition"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"meta":{"$ref":"#/components/schemas/DataMeta"}},"type":"object","required":["items","total","page","page_size","total_pages","meta"],"title":"DataPage[DataStageTransition]"},"DataPipelineStage":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"stage_type":{"type":"string","title":"Stage Type"},"sort_order":{"type":"integer","title":"Sort Order"},"is_terminal":{"type":"boolean","title":"Is Terminal"},"is_optional":{"type":"boolean","title":"Is Optional"}},"type":"object","required":["id","name","stage_type","sort_order","is_terminal","is_optional"],"title":"DataPipelineStage"},"DataStageTransition":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"change_type":{"type":"string","title":"Change Type"},"from_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"From Stage Id"},"from_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Stage Name"},"from_stage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Stage Type"},"to_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"To Stage Id"},"to_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Stage Name"},"to_stage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Stage Type"},"from_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Status"},"to_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Status"},"changed_at":{"type":"string","format":"date-time","title":"Changed At"},"changed_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Changed By User Id"},"changed_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Changed By Name"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["id","application_id","candidate_id","job_id","change_type","from_stage_id","from_stage_name","from_stage_type","to_stage_id","to_stage_name","to_stage_type","from_status","to_status","changed_at","changed_by_user_id","changed_by_name","notes"],"title":"DataStageTransition"},"DeleteMemberRequest":{"properties":{"confirm_text":{"type":"string","maxLength":255,"minLength":1,"title":"Confirm Text"}},"type":"object","required":["confirm_text"],"title":"DeleteMemberRequest","description":"Confirmation payload for hard-deleting a teammate.\n\n``confirm_text`` must match the target's ``full_name`` OR ``email`` (after a\nsurrounding-whitespace strip) — friction so a member can't be removed by an\naccidental click (mirrors the delete-workspace confirm). Hard-delete is\nirreversible; the target's owned data transfers to the acting admin."},"DeleteWorkspaceRequest":{"properties":{"confirm_text":{"type":"string","maxLength":255,"minLength":1,"title":"Confirm Text"}},"type":"object","required":["confirm_text"],"title":"DeleteWorkspaceRequest","description":"Confirmation payload for permanently deleting the current workspace.\n\n``confirm_text`` must match the tenant's ``company_name`` exactly (after a\nsurrounding-whitespace strip). This is a deliberate friction step so a\nworkspace can't be destroyed by an accidental click."},"DemographicCount":{"properties":{"label":{"type":"string","title":"Label"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["label","count"],"title":"DemographicCount","description":"A single bucket in a demographics breakdown."},"DemographicsResponse":{"properties":{"gender_distribution":{"items":{"$ref":"#/components/schemas/DemographicCount"},"type":"array","title":"Gender Distribution"},"location_distribution":{"items":{"$ref":"#/components/schemas/DemographicCount"},"type":"array","title":"Location Distribution"}},"type":"object","required":["gender_distribution","location_distribution"],"title":"DemographicsResponse","description":"Gender and location distribution of candidates."},"DuplicateCheckResponse":{"properties":{"has_duplicate":{"type":"boolean","title":"Has Duplicate"},"matches":{"items":{"$ref":"#/components/schemas/DuplicateMatch"},"type":"array","title":"Matches","default":[]}},"type":"object","required":["has_duplicate"],"title":"DuplicateCheckResponse","description":"Response from the check-duplicate endpoint."},"DuplicateMatch":{"properties":{"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"match_type":{"type":"string","title":"Match Type"}},"type":"object","required":["candidate_id","candidate_code","full_name","match_type"],"title":"DuplicateMatch","description":"A single duplicate candidate match."},"EmailAttachment":{"properties":{"filename":{"type":"string","title":"Filename"},"url":{"type":"string","title":"Url"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"}},"type":"object","required":["filename","url"],"title":"EmailAttachment","description":"File attachment for an email."},"EmailAutomationRuleCreate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"stage_trigger":{"type":"string","maxLength":30,"title":"Stage Trigger"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"template_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Template Ids"},"send_mode":{"type":"string","enum":["auto_send","manual_confirm"],"title":"Send Mode"},"priority":{"type":"integer","title":"Priority","default":0},"is_active":{"type":"boolean","title":"Is Active","default":true},"recipients":{"items":{"type":"string","enum":["candidate","hiring_manager"]},"type":"array","title":"Recipients"}},"type":"object","required":["stage_trigger","template_id","send_mode"],"title":"EmailAutomationRuleCreate","description":"Create an automation rule attaching a template to a stage trigger."},"EmailAutomationRuleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"stage_trigger":{"type":"string","title":"Stage Trigger"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"template_name":{"type":"string","title":"Template Name"},"template_subject":{"type":"string","title":"Template Subject"},"template_body":{"type":"string","title":"Template Body"},"template_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Template Ids"},"template_names":{"items":{"type":"string"},"type":"array","title":"Template Names"},"send_mode":{"type":"string","enum":["auto_send","manual_confirm"],"title":"Send Mode"},"priority":{"type":"integer","title":"Priority"},"is_active":{"type":"boolean","title":"Is Active"},"recipients":{"items":{"type":"string","enum":["candidate","hiring_manager"]},"type":"array","title":"Recipients"},"sent_count":{"type":"integer","title":"Sent Count","default":0},"created_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Email"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","stage_trigger","template_id","template_name","template_subject","template_body","send_mode","priority","is_active","recipients","created_at","updated_at"],"title":"EmailAutomationRuleResponse","description":"Response shape for a rule. Includes inline template snapshot so the\nFE Automation page renders without a second roundtrip."},"EmailAutomationRuleUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"stage_trigger":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Stage Trigger"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"template_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Template Ids"},"send_mode":{"anyOf":[{"type":"string","enum":["auto_send","manual_confirm"]},{"type":"null"}],"title":"Send Mode"},"priority":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priority"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"recipients":{"anyOf":[{"items":{"type":"string","enum":["candidate","hiring_manager"]},"type":"array"},{"type":"null"}],"title":"Recipients"}},"type":"object","title":"EmailAutomationRuleUpdate","description":"Patch a rule. send_mode/template_id/stage_trigger changes go through\nthe same mutex+sensitive-stage checks as create."},"EmailIntegrationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"sender_email":{"type":"string","title":"Sender Email"},"status":{"type":"string","title":"Status"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","provider","sender_email","status","created_at","updated_at"],"title":"EmailIntegrationResponse","description":"One row of user_email_integrations, scrubbed of token material."},"EmailLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"to_email":{"type":"string","title":"To Email"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"status":{"type":"string","title":"Status"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"resend_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resend Id"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"attachments":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Attachments"},"cc_emails":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Cc Emails"},"followup_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Followup Of Id"},"followup_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Followup Status"},"has_reply":{"type":"boolean","title":"Has Reply","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"template_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Name"}},"type":"object","required":["id","tenant_id","template_id","candidate_id","application_id","to_email","subject","body","status","sent_at","error_message","resend_id","created_at"],"title":"EmailLogResponse","description":"Response schema for an email log entry."},"EmailPreviewRequest":{"properties":{"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}},"type":"object","required":["candidate_id"],"title":"EmailPreviewRequest","description":"Request to preview an email with variables replaced."},"EmailPreviewResponse":{"properties":{"to_email":{"type":"string","title":"To Email","default":""},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"candidate_name":{"type":"string","title":"Candidate Name"},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateAttachment"},"type":"array"},{"type":"null"}],"title":"Attachments"},"missing_variables":{"items":{"type":"string"},"type":"array","title":"Missing Variables","default":[]}},"type":"object","required":["subject","body","candidate_name"],"title":"EmailPreviewResponse","description":"Preview response with rendered email content."},"EmailReplyResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email_log_id":{"type":"string","format":"uuid","title":"Email Log Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"from_email":{"type":"string","title":"From Email"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Text"},"body_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Html"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"intent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intent"},"intent_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Intent Confidence"},"attachments":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Attachments"}},"type":"object","required":["id","email_log_id","candidate_id","from_email","subject","body_text","body_html","received_at","created_at"],"title":"EmailReplyResponse","description":"Response schema for an email reply."},"EmailSendRequest":{"properties":{"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"to_email":{"type":"string","format":"email","title":"To Email"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/EmailAttachment"},"type":"array"},{"type":"null"}],"title":"Attachments"},"cc_emails":{"anyOf":[{"items":{"type":"string","format":"email"},"type":"array"},{"type":"null"}],"title":"Cc Emails"},"followup_delay_hours":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Followup Delay Hours"},"followup_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Followup Template Id"}},"type":"object","required":["candidate_id","to_email","subject","body"],"title":"EmailSendRequest","description":"Request to send an email."},"EmailSendResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"status":{"type":"string","title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["log_id","status"],"title":"EmailSendResponse","description":"Response after sending an email."},"EmailTemplateCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"stage_trigger":{"type":"string","maxLength":30,"title":"Stage Trigger"},"stage_type":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Stage Type"},"subject":{"type":"string","maxLength":500,"title":"Subject"},"body":{"type":"string","title":"Body"},"is_active":{"type":"boolean","title":"Is Active","default":true},"send_mode":{"type":"string","enum":["auto_send","manual_confirm"],"title":"Send Mode","default":"manual_confirm"},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateAttachment"},"type":"array"},{"type":"null"}],"title":"Attachments"}},"type":"object","required":["name","stage_trigger","subject","body"],"title":"EmailTemplateCreate","description":"Schema for creating an email template."},"EmailTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"stage_trigger":{"type":"string","title":"Stage Trigger"},"stage_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Type"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"is_active":{"type":"boolean","title":"Is Active"},"send_mode":{"type":"string","enum":["auto_send","manual_confirm"],"title":"Send Mode"},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateAttachment"},"type":"array"},{"type":"null"}],"title":"Attachments"},"created_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Email"},"system_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Key"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","stage_trigger","subject","body","is_active","send_mode","created_at","updated_at"],"title":"EmailTemplateResponse","description":"Response schema for an email template."},"EmailTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"stage_trigger":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Stage Trigger"},"stage_type":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Stage Type"},"subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"send_mode":{"anyOf":[{"type":"string","enum":["auto_send","manual_confirm"]},{"type":"null"}],"title":"Send Mode"},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateAttachment"},"type":"array"},{"type":"null"}],"title":"Attachments"}},"type":"object","title":"EmailTemplateUpdate","description":"Schema for updating an email template."},"EmploymentType":{"type":"string","enum":["full_time","part_time","contract","internship"],"title":"EmploymentType","description":"Types of employment."},"EnrollRequest":{"properties":{"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","minItems":1,"title":"Candidate Ids"}},"type":"object","required":["candidate_ids"],"title":"EnrollRequest","description":"Schema for manually enrolling candidates."},"EnrollResultResponse":{"properties":{"enrolled":{"type":"integer","title":"Enrolled"},"skipped":{"type":"integer","title":"Skipped"},"details":{"items":{"type":"string"},"type":"array","title":"Details"}},"type":"object","required":["enrolled","skipped"],"title":"EnrollResultResponse","description":"Response for bulk enrollment."},"EnrollmentActionRequest":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"EnrollmentActionRequest","description":"Schema for stopping an enrollment with a reason."},"EnrollmentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"sequence_id":{"type":"string","format":"uuid","title":"Sequence Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"status":{"type":"string","title":"Status"},"current_step_order":{"type":"integer","title":"Current Step Order"},"next_send_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Send At"},"enrolled_at":{"type":"string","format":"date-time","title":"Enrolled At"},"paused_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paused At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"stopped_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Stopped At"},"stop_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stop Reason"},"enrolled_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Enrolled By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"}},"type":"object","required":["id","tenant_id","sequence_id","candidate_id","status","current_step_order","enrolled_at","created_at"],"title":"EnrollmentResponse","description":"Response schema for a drip enrollment."},"EvaluationCreate":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Interview Id"},"evaluator_type":{"type":"string","pattern":"^(internal|external)$","title":"Evaluator Type","default":"internal"},"evaluator_name":{"type":"string","maxLength":200,"minLength":1,"title":"Evaluator Name"},"evaluator_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Evaluator Email"},"overall_rating":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Overall Rating"},"rating_scale":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Rating Scale","default":5},"criteria_scores":{"anyOf":[{"items":{"$ref":"#/components/schemas/CriterionScoreInput"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"comments":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Comments"},"result":{"anyOf":[{"type":"string","pattern":"^(strong_hire|hire|no_hire|passed|failed|not_passed|neutral|pending)$"},{"type":"null"}],"title":"Result"},"source":{"type":"string","pattern":"^(manual|external_token|on_behalf|migrated|hm_review)$","title":"Source","default":"manual"},"evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evaluated At"}},"type":"object","required":["application_id","evaluator_name"],"title":"EvaluationCreate","description":"Schema for creating an evaluation."},"EvaluationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Interview Id"},"evaluator_type":{"type":"string","title":"Evaluator Type"},"evaluator_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Evaluator Id"},"evaluator_name":{"type":"string","title":"Evaluator Name"},"evaluator_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluator Email"},"overall_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overall Rating"},"rating_scale":{"type":"integer","title":"Rating Scale"},"criteria_scores":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"weighted_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weighted Score"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"source":{"type":"string","title":"Source"},"evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evaluated At"},"is_deleted":{"type":"boolean","title":"Is Deleted"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","application_id","interview_id","evaluator_type","evaluator_id","evaluator_name","evaluator_email","overall_rating","rating_scale","criteria_scores","weighted_score","comments","result","source","evaluated_at","is_deleted","created_at","updated_at"],"title":"EvaluationResponse","description":"Response schema for an evaluation."},"EvaluationSummary":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"total_evaluations":{"type":"integer","title":"Total Evaluations"},"average_rating":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Average Rating"},"average_weighted_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Average Weighted Score"},"results":{"additionalProperties":true,"type":"object","title":"Results"},"criteria_averages":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Criteria Averages"}},"type":"object","required":["application_id","total_evaluations","average_rating","average_weighted_score","results","criteria_averages"],"title":"EvaluationSummary","description":"Aggregated evaluation summary for an application."},"EvaluationTemplateCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"rating_scale":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Rating Scale","default":5},"has_score":{"type":"boolean","title":"Has Score","default":true},"has_notes":{"type":"boolean","title":"Has Notes","default":true},"criteria":{"items":{"$ref":"#/components/schemas/CriterionInput"},"type":"array","title":"Criteria"},"is_default":{"type":"boolean","title":"Is Default","default":false}},"type":"object","required":["name"],"title":"EvaluationTemplateCreate","description":"Schema for creating an evaluation template."},"EvaluationTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"rating_scale":{"type":"integer","title":"Rating Scale"},"has_score":{"type":"boolean","title":"Has Score","default":true},"has_notes":{"type":"boolean","title":"Has Notes","default":true},"criteria":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Criteria"},"is_default":{"type":"boolean","title":"Is Default"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","description","rating_scale","criteria","is_default","created_by","created_at","updated_at"],"title":"EvaluationTemplateResponse","description":"Response schema for an evaluation template."},"EvaluationTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"rating_scale":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Rating Scale"},"has_score":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Score"},"has_notes":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Notes"},"criteria":{"anyOf":[{"items":{"$ref":"#/components/schemas/CriterionInput"},"type":"array"},{"type":"null"}],"title":"Criteria"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"}},"type":"object","title":"EvaluationTemplateUpdate","description":"Schema for updating an evaluation template."},"EvaluationUpdate":{"properties":{"overall_rating":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Overall Rating"},"criteria_scores":{"anyOf":[{"items":{"$ref":"#/components/schemas/CriterionScoreInput"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"comments":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Comments"},"result":{"anyOf":[{"type":"string","pattern":"^(strong_hire|hire|no_hire|passed|failed|not_passed|neutral|pending)$"},{"type":"null"}],"title":"Result"}},"type":"object","title":"EvaluationUpdate","description":"Schema for updating an evaluation."},"EventPayload":{"properties":{"event_type":{"type":"string","maxLength":50,"title":"Event Type"},"source_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Source Url"},"referrer_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Referrer Url"},"tenant_id":{"anyOf":[{"type":"string","maxLength":36},{"type":"null"}],"title":"Tenant Id"},"event_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Event Metadata"},"utm_source":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Utm Source"},"utm_medium":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Utm Medium"},"utm_campaign":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Utm Campaign"},"utm_content":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Utm Content"}},"type":"object","required":["event_type"],"title":"EventPayload"},"ExportJobCreate":{"properties":{"export_type":{"type":"string","title":"Export Type","default":"candidates"},"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filters"},"candidate_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Candidate Ids"}},"type":"object","title":"ExportJobCreate","description":"Request to create a new export job."},"ExportJobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"export_type":{"type":"string","title":"Export Type"},"status":{"type":"string","title":"Status"},"filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filters"},"candidate_ids":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Candidate Ids"},"file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Url"},"file_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Name"},"total_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Rows"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","tenant_id","created_by","export_type","status","filters","candidate_ids","file_url","file_name","total_rows","error_message","created_at","completed_at"],"title":"ExportJobResponse","description":"Full export job response."},"ExportJobStatusResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","title":"Status"},"file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Url"},"file_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Name"},"total_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Rows"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","status","file_url","file_name","total_rows","error_message","created_at","completed_at"],"title":"ExportJobStatusResponse","description":"Lightweight response for polling status."},"ExternalTeamMemberSuggestion":{"properties":{"name":{"type":"string","title":"Name"},"role":{"type":"string","title":"Role","default":""},"email":{"type":"string","title":"Email"}},"type":"object","required":["name","email"],"title":"ExternalTeamMemberSuggestion"},"ExtraSharedLink":{"properties":{"url":{"type":"string","maxLength":2000,"title":"Url"},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Label"},"link_type":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Link Type"}},"type":"object","required":["url"],"title":"ExtraSharedLink","description":"Inline URL not stored as a CandidateLink row (e.g. CV-parsed)."},"FieldOptionSchema":{"properties":{"value":{"type":"string","title":"Value"},"label":{"type":"string","title":"Label"}},"type":"object","required":["value","label"],"title":"FieldOptionSchema","description":"A single option for select-type fields."},"FieldValidationSchema":{"properties":{"pattern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pattern"},"pattern_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pattern Error"},"min_value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Value"},"max_file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max File Size"},"allowed_extensions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Extensions"},"max_length":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Length"}},"type":"object","title":"FieldValidationSchema","description":"Validation rules sent to the frontend."},"FilterPreviewResponse":{"properties":{"total_count":{"type":"integer","title":"Total Count"},"sample_candidates":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sample Candidates"}},"type":"object","required":["total_count","sample_candidates"],"title":"FilterPreviewResponse","description":"Response for filter preview."},"ForgotPasswordRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ForgotPasswordRequest","description":"Request a password reset email."},"FunnelStageMeta":{"properties":{"stage":{"type":"string","title":"Stage"},"applies":{"type":"integer","title":"Applies"},"total":{"type":"integer","title":"Total"},"alt_labels":{"items":{"type":"string"},"type":"array","title":"Alt Labels"}},"type":"object","required":["stage","applies","total","alt_labels"],"title":"FunnelStageMeta","description":"Per-funnel-stage template coverage for the \"All pipelines\" report view.\n\nOnly populated when the report is NOT scoped to one template and the cohort\nspans >=2 templates. Lets the funnel flag stages that only SOME pipelines have\n(a diluted denominator) and surface the custom names collapsed into each band."},"Gender":{"type":"string","enum":["male","female","other"],"title":"Gender","description":"Candidate gender."},"GoogleAuthRequest":{"properties":{"id_token":{"type":"string","title":"Id Token"},"company_name":{"anyOf":[{"type":"string","maxLength":255,"minLength":2},{"type":"null"}],"title":"Company Name"}},"type":"object","required":["id_token"],"title":"GoogleAuthRequest","description":"Google OAuth: pass the ID token from frontend."},"HMReviewListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/HMReviewRequestResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"HMReviewListResponse","description":"List of HM reviews."},"HMReviewRequestCreate":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"reviewer_email":{"type":"string","format":"email","title":"Reviewer Email"},"reviewer_name":{"type":"string","maxLength":200,"minLength":1,"title":"Reviewer Name"},"note_to_reviewer":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Note To Reviewer"},"deadline_days":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Deadline Days","default":3},"send_email":{"type":"boolean","title":"Send Email","default":true},"shared_info":{"anyOf":[{"$ref":"#/components/schemas/HMReviewSharedInfo"},{"type":"null"}]},"move_to_hm_review_stage":{"type":"boolean","title":"Move To Hm Review Stage","default":false}},"type":"object","required":["application_id","reviewer_email","reviewer_name"],"title":"HMReviewRequestCreate","description":"Schema for requesting an HM review."},"HMReviewRequestResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"evaluation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluation Type"},"evaluator_name":{"type":"string","title":"Evaluator Name"},"evaluator_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluator Email"},"note_to_evaluator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note To Evaluator"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"},"deadline_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deadline At"},"reminder_count":{"type":"integer","title":"Reminder Count"},"max_reminders":{"type":"integer","title":"Max Reminders","default":3},"source":{"type":"string","title":"Source"},"email_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Status"},"shared_info":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Shared Info"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evaluated At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"}},"type":"object","required":["id","tenant_id","application_id","evaluation_type","evaluator_name","evaluator_email","note_to_evaluator","result","comments","deadline_at","reminder_count","source","created_at","updated_at"],"title":"HMReviewRequestResponse","description":"Response schema for an HM review request."},"HMReviewSharedInfo":{"properties":{"include_cv":{"type":"boolean","title":"Include Cv","default":true},"include_attachments":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Include Attachments"},"include_links":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Include Links"},"extra_links":{"items":{"$ref":"#/components/schemas/ExtraSharedLink"},"type":"array","title":"Extra Links"},"include_skills":{"type":"boolean","title":"Include Skills","default":false},"include_experience":{"type":"boolean","title":"Include Experience","default":false},"include_education":{"type":"boolean","title":"Include Education","default":false},"include_salary":{"type":"boolean","title":"Include Salary","default":false},"include_matching_score":{"type":"boolean","title":"Include Matching Score","default":false},"include_hr_review":{"type":"boolean","title":"Include Hr Review","default":false}},"type":"object","title":"HMReviewSharedInfo","description":"What candidate info to share with the HM reviewer."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HandbookFeedbackIn":{"properties":{"article_slug":{"type":"string","maxLength":100,"minLength":1,"title":"Article Slug"},"category_slug":{"type":"string","maxLength":50,"minLength":1,"title":"Category Slug"},"sentiment":{"type":"string","title":"Sentiment","description":"helpful | not_helpful"},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment"},"lang":{"type":"string","maxLength":5,"title":"Lang","default":"vi"}},"type":"object","required":["article_slug","category_slug","sentiment"],"title":"HandbookFeedbackIn"},"HandbookFeedbackOut":{"properties":{"ok":{"type":"boolean","title":"Ok","default":true},"received_at":{"type":"string","format":"date-time","title":"Received At"}},"type":"object","required":["received_at"],"title":"HandbookFeedbackOut"},"HiredListItem":{"properties":{"application_id":{"type":"string","title":"Application Id"},"candidate_id":{"type":"string","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"recruiter_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recruiter Name"},"hired_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hired Date"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"time_to_hire_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Time To Hire Days"}},"type":"object","required":["application_id","candidate_id","candidate_name","job_title"],"title":"HiredListItem","description":"A single hired candidate entry for the Hired List table."},"HiredListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/HiredListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"HiredListResponse","description":"Paginated hired list response."},"HiringStage":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"duration":{"type":"string","title":"Duration"},"owner":{"type":"string","title":"Owner"}},"type":"object","required":["id","name","duration","owner"],"title":"HiringStage","description":"A single stage in the hiring process pipeline."},"HistoryItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"performed_at":{"type":"string","format":"date-time","title":"Performed At"},"performed_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Performed By"},"operation":{"type":"string","title":"Operation"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"affected_count":{"type":"integer","title":"Affected Count"},"undone_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Undone At"}},"type":"object","required":["id","performed_at","performed_by","operation","description","affected_count","undone_at"],"title":"HistoryItem","description":"One entry in the source-cleanup history."},"HistoryResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/HistoryItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"HistoryResponse","description":"Response from GET /source-management/history."},"IntegrationConnectedResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"provider":{"type":"string","title":"Provider"},"sender_email":{"type":"string","title":"Sender Email"}},"type":"object","required":["success","provider","sender_email"],"title":"IntegrationConnectedResponse"},"InterviewCandidateResponseMark":{"properties":{"action":{"type":"string","pattern":"^(accept|decline)$","title":"Action"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"}},"type":"object","required":["action"],"title":"InterviewCandidateResponseMark","description":"Recruiter manually marks candidate response (verbal confirmation etc.)."},"InterviewConflict":{"properties":{"interviewer_email":{"type":"string","title":"Interviewer Email"},"interviewer_name":{"type":"string","title":"Interviewer Name"},"conflicting_interview_id":{"type":"string","format":"uuid","title":"Conflicting Interview Id"},"conflicting_time":{"type":"string","format":"date-time","title":"Conflicting Time"},"conflicting_candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conflicting Candidate Name"}},"type":"object","required":["interviewer_email","interviewer_name","conflicting_interview_id","conflicting_time"],"title":"InterviewConflict","description":"A detected scheduling conflict for an interviewer."},"InterviewConflictCheck":{"properties":{"interviewer_emails":{"items":{"type":"string"},"type":"array","title":"Interviewer Emails"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","maximum":480.0,"minimum":15.0,"title":"Duration Minutes","default":60},"exclude_interview_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Exclude Interview Id"}},"type":"object","required":["interviewer_emails","scheduled_at"],"title":"InterviewConflictCheck","description":"Schema for checking interviewer conflicts."},"InterviewCreate":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_round":{"type":"string","maxLength":100,"title":"Interview Round","default":"Round 1"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","maximum":480.0,"minimum":15.0,"title":"Duration Minutes","default":60},"location":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Meeting Link"},"interviewers":{"items":{"$ref":"#/components/schemas/InterviewerInput"},"type":"array","minItems":1,"title":"Interviewers"},"agenda":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Agenda"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"create_calendar_event":{"type":"boolean","title":"Create Calendar Event","default":false},"include_profile_link":{"type":"boolean","title":"Include Profile Link","default":true},"send_interviewer_emails":{"type":"boolean","title":"Send Interviewer Emails","default":false},"send_candidate_email":{"type":"boolean","title":"Send Candidate Email","default":true},"candidate_email_intro":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Candidate Email Intro"},"email_subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Email Subject"},"email_locale":{"type":"string","pattern":"^(vi|en)$","title":"Email Locale","default":"vi"},"auto_move_to_interview":{"type":"boolean","title":"Auto Move To Interview","default":false},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled","default":true},"feedback_reminders_enabled":{"type":"boolean","title":"Feedback Reminders Enabled","default":false},"evaluation_form":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evaluation Form"}},"type":"object","required":["application_id","scheduled_at","interviewers"],"title":"InterviewCreate","description":"Schema for scheduling an interview."},"InterviewFeedbackSubmit":{"properties":{"rating":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Rating"},"feedback":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Feedback"},"feedback_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Feedback Data"},"result":{"type":"string","pattern":"^(strong_hire|hire|no_hire|passed|failed|not_passed|neutral|pending)$","title":"Result","default":"no_hire"}},"type":"object","required":["rating"],"title":"InterviewFeedbackSubmit","description":"Schema for submitting interview feedback."},"InterviewReschedule":{"properties":{"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"anyOf":[{"type":"integer","maximum":480.0,"minimum":15.0},{"type":"null"}],"title":"Duration Minutes"},"reschedule_reason":{"type":"string","maxLength":2000,"minLength":1,"title":"Reschedule Reason"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"update_calendar":{"type":"boolean","title":"Update Calendar","default":true},"include_profile_link":{"type":"boolean","title":"Include Profile Link","default":true},"send_notifications":{"type":"boolean","title":"Send Notifications","default":true},"email_locale":{"type":"string","pattern":"^(vi|en)$","title":"Email Locale","default":"vi"}},"type":"object","required":["scheduled_at","reschedule_reason"],"title":"InterviewReschedule","description":"Schema for rescheduling an interview (creates new, marks old as rescheduled)."},"InterviewResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_round":{"type":"string","title":"Interview Round"},"round_number":{"type":"integer","title":"Round Number"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewer_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Ids"},"interviewer_names":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Names"},"interviewer_emails":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Emails"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"status":{"type":"string","title":"Status"},"result":{"type":"string","title":"Result"},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"feedback_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Feedback Data"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"reschedule_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reschedule Reason"},"rescheduled_from":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rescheduled From"},"calendar_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Event Id"},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled","default":true},"feedback_reminders_enabled":{"type":"boolean","title":"Feedback Reminders Enabled","default":false},"is_self_schedule":{"type":"boolean","title":"Is Self Schedule","default":false},"evaluation_form":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evaluation Form"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"stage_moved_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Moved To"},"emails_sent_to_candidate":{"type":"boolean","title":"Emails Sent To Candidate","default":false},"emails_sent_to_interviewers":{"type":"boolean","title":"Emails Sent To Interviewers","default":false}},"type":"object","required":["id","tenant_id","application_id","interview_round","round_number","scheduled_at","duration_minutes","location","meeting_link","interviewer_ids","interviewer_names","interviewer_emails","agenda","status","result","feedback","rating","feedback_data","notes","reschedule_reason","rescheduled_from","calendar_event_id","created_by","created_at","updated_at"],"title":"InterviewResponse","description":"Full response schema for an interview."},"InterviewSelfScheduleCreate":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_round":{"type":"string","maxLength":100,"title":"Interview Round","default":"Round 1"},"slots":{"items":{"$ref":"#/components/schemas/SelfScheduleSlotInput"},"type":"array","maxItems":20,"minItems":1,"title":"Slots"},"location":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Meeting Link"},"interviewers":{"items":{"$ref":"#/components/schemas/InterviewerInput"},"type":"array","title":"Interviewers"},"agenda":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Agenda"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"send_candidate_email":{"type":"boolean","title":"Send Candidate Email","default":true},"candidate_email_intro":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Candidate Email Intro"},"email_subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Email Subject"},"email_locale":{"type":"string","pattern":"^(vi|en)$","title":"Email Locale","default":"vi"},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled","default":true},"feedback_reminders_enabled":{"type":"boolean","title":"Feedback Reminders Enabled","default":false}},"type":"object","required":["application_id","slots"],"title":"InterviewSelfScheduleCreate","description":"Schema for creating a self-schedule interview."},"InterviewTemplateCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"duration_minutes":{"type":"integer","maximum":480.0,"minimum":15.0,"title":"Duration Minutes","default":60},"location":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Meeting Link"},"agenda":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Agenda"},"default_interviewers":{"anyOf":[{"items":{"$ref":"#/components/schemas/InterviewerInput"},"type":"array"},{"type":"null"}],"title":"Default Interviewers"},"send_interviewer_emails":{"type":"boolean","title":"Send Interviewer Emails","default":true},"send_candidate_email":{"type":"boolean","title":"Send Candidate Email","default":true},"candidate_email_intro":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Candidate Email Intro"},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled","default":true}},"type":"object","required":["name"],"title":"InterviewTemplateCreate","description":"Schema for creating an interview template."},"InterviewTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"default_interviewers":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Default Interviewers"},"send_interviewer_emails":{"type":"boolean","title":"Send Interviewer Emails"},"send_candidate_email":{"type":"boolean","title":"Send Candidate Email"},"candidate_email_intro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email Intro"},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled"},"evaluation_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Evaluation Template Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","description","duration_minutes","location","meeting_link","agenda","default_interviewers","send_interviewer_emails","send_candidate_email","candidate_email_intro","reminders_enabled","created_by","created_at","updated_at"],"title":"InterviewTemplateResponse","description":"Response schema for an interview template."},"InterviewTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"duration_minutes":{"anyOf":[{"type":"integer","maximum":480.0,"minimum":15.0},{"type":"null"}],"title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"default_interviewers":{"anyOf":[{"items":{"$ref":"#/components/schemas/InterviewerInput"},"type":"array"},{"type":"null"}],"title":"Default Interviewers"},"send_interviewer_emails":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Send Interviewer Emails"},"send_candidate_email":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Send Candidate Email"},"candidate_email_intro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email Intro"},"reminders_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Reminders Enabled"}},"type":"object","title":"InterviewTemplateUpdate","description":"Schema for updating an interview template."},"InterviewUpdate":{"properties":{"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"duration_minutes":{"anyOf":[{"type":"integer","maximum":480.0,"minimum":15.0},{"type":"null"}],"title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewers":{"anyOf":[{"items":{"$ref":"#/components/schemas/InterviewerInput"},"type":"array"},{"type":"null"}],"title":"Interviewers"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"InterviewUpdate","description":"Schema for updating interview scheduling details."},"InterviewWithContextResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"interview_round":{"type":"string","title":"Interview Round"},"round_number":{"type":"integer","title":"Round Number"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewer_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Ids"},"interviewer_names":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Names"},"interviewer_emails":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interviewer Emails"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"status":{"type":"string","title":"Status"},"result":{"type":"string","title":"Result"},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"feedback_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Feedback Data"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"reschedule_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reschedule Reason"},"rescheduled_from":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rescheduled From"},"calendar_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Event Id"},"reminders_enabled":{"type":"boolean","title":"Reminders Enabled","default":true},"feedback_reminders_enabled":{"type":"boolean","title":"Feedback Reminders Enabled","default":false},"is_self_schedule":{"type":"boolean","title":"Is Self Schedule","default":false},"evaluation_form":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evaluation Form"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"stage_moved_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Moved To"},"emails_sent_to_candidate":{"type":"boolean","title":"Emails Sent To Candidate","default":false},"emails_sent_to_interviewers":{"type":"boolean","title":"Emails Sent To Interviewers","default":false},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Code"}},"type":"object","required":["id","tenant_id","application_id","interview_round","round_number","scheduled_at","duration_minutes","location","meeting_link","interviewer_ids","interviewer_names","interviewer_emails","agenda","status","result","feedback","rating","feedback_data","notes","reschedule_reason","rescheduled_from","calendar_event_id","created_by","created_at","updated_at"],"title":"InterviewWithContextResponse","description":"Interview response with candidate and job context."},"InterviewerContactCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"}},"type":"object","required":["name","email"],"title":"InterviewerContactCreate","description":"Schema for creating an interviewer contact."},"InterviewerContactResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","email","phone","title","company","notes","created_by","created_at","updated_at"],"title":"InterviewerContactResponse","description":"Response schema for an interviewer contact."},"InterviewerContactUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"InterviewerContactUpdate","description":"Schema for updating an interviewer contact."},"InterviewerInput":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["name","email"],"title":"InterviewerInput","description":"An external interviewer identified by name + email."},"InviteInfoResponse":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"company_name":{"type":"string","title":"Company Name"}},"type":"object","required":["email","role","company_name"],"title":"InviteInfoResponse","description":"Public info about a pending invite, shown on the accept-invite page so\nthe invitee can see which email their new account will use (prevents the\n\"typed my email into the Full Name box\" lockout — incident 2026-06-23)."},"InviteLookupRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"InviteLookupRequest","description":"Look up an invite token's invited email (for the accept-invite page)."},"InviteRegisterRequest":{"properties":{"token":{"type":"string","title":"Token"},"full_name":{"type":"string","maxLength":255,"minLength":2,"title":"Full Name"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"}},"type":"object","required":["token","full_name","password"],"title":"InviteRegisterRequest","description":"Register via invite token."},"InviteRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"role":{"type":"string","pattern":"^(admin|recruiter|hiring_manager)$","title":"Role","default":"recruiter"}},"type":"object","required":["email"],"title":"InviteRequest","description":"Admin creates an invite."},"InviteResponse":{"properties":{"invite_url":{"type":"string","title":"Invite Url"},"email":{"type":"string","title":"Email"},"expires_in_hours":{"type":"integer","title":"Expires In Hours"}},"type":"object","required":["invite_url","email","expires_in_hours"],"title":"InviteResponse","description":"Response after creating an invite."},"ItviecConnectRequest":{"properties":{"client_id":{"type":"string","maxLength":255,"minLength":6,"title":"Client Id"},"client_secret":{"type":"string","minLength":6,"format":"password","title":"Client Secret","writeOnly":true}},"type":"object","required":["client_id","client_secret"],"title":"ItviecConnectRequest"},"ItviecJobLinkItem":{"properties":{"external_job_id":{"type":"string","title":"External Job Id"},"external_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Job Title"},"destination":{"type":"string","enum":["job","talent_pool","off"],"title":"Destination"},"tickup_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tickup Job Id"},"tickup_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tickup Job Title"},"tickup_job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tickup Job Code"},"suggested_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suggested Job Id"},"suggested_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggested Job Title"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Synced At"},"live_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Live Status"},"live_applications":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Live Applications"}},"type":"object","required":["external_job_id","destination"],"title":"ItviecJobLinkItem"},"ItviecJobsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ItviecJobLinkItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"ItviecJobsResponse"},"ItviecLinkUpdateRequest":{"properties":{"destination":{"type":"string","enum":["job","talent_pool","off"],"title":"Destination"},"tickup_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tickup Job Id"}},"type":"object","required":["destination"],"title":"ItviecLinkUpdateRequest"},"ItviecSettingsUpdateRequest":{"properties":{"import_since":{"type":"string","format":"date-time","title":"Import Since"}},"type":"object","required":["import_since"],"title":"ItviecSettingsUpdateRequest"},"ItviecStatusResponse":{"properties":{"connected":{"type":"boolean","title":"Connected"},"client_id_masked":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id Masked"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"import_since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Import Since"},"last_sync_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Sync At"},"last_sync_summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Last Sync Summary"}},"type":"object","required":["connected"],"title":"ItviecStatusResponse"},"ItviecSyncTriggerResponse":{"properties":{"started":{"type":"boolean","title":"Started"}},"type":"object","required":["started"],"title":"ItviecSyncTriggerResponse"},"JobAttention":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Code"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"days_open":{"type":"integer","title":"Days Open","default":0},"active_candidates":{"type":"integer","title":"Active Candidates","default":0},"stale_candidates":{"type":"integer","title":"Stale Candidates","default":0},"reason":{"type":"string","title":"Reason","default":""}},"type":"object","required":["job_id","title"],"title":"JobAttention"},"JobAttributeCount":{"properties":{"key":{"type":"string","title":"Key"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["key","count"],"title":"JobAttributeCount","description":"One slice in the employment-type or work-setup donut."},"JobCreate":{"properties":{"title":{"type":"string","maxLength":255,"minLength":1,"title":"Title"},"department":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Department"},"locations":{"anyOf":[{"items":{"$ref":"#/components/schemas/LocationInput"},"type":"array"},{"type":"null"}],"title":"Locations"},"employment_type":{"$ref":"#/components/schemas/EmploymentType","default":"full_time"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"additional_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Info"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"required_experience_years":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Required Experience Years"},"hiring_process":{"anyOf":[{"items":{"$ref":"#/components/schemas/HiringStage"},"type":"array"},{"type":"null"}],"title":"Hiring Process"},"status":{"$ref":"#/components/schemas/JobStatus","default":"draft"},"salary_min":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Salary Type","default":"gross"},"salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Salary Period","default":"monthly"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"negotiable":{"type":"boolean","title":"Negotiable","default":false},"headcount":{"type":"integer","minimum":1.0,"title":"Headcount","default":1},"hire_type":{"anyOf":[{"type":"string","pattern":"^(new_hire|replacement)$"},{"type":"null"}],"title":"Hire Type"},"required_languages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Required Languages"},"expected_hire_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expected Hire Date"},"publish_to_career_site":{"type":"boolean","title":"Publish To Career Site","default":false},"recruitment_cost_items":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecruitmentCostItem-Input"},"type":"array"},{"type":"null"}],"title":"Recruitment Cost Items"},"cost_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Cost Currency"},"hiring_stages":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Stages"},"pipeline_stages":{"anyOf":[{"items":{"$ref":"#/components/schemas/PipelineStageCreate"},"type":"array"},{"type":"null"}],"title":"Pipeline Stages"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"hiring_team_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Team Ids"},"hiring_team_external":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Team External"}},"type":"object","required":["title"],"title":"JobCreate","description":"Schema for creating a new job."},"JobDeleteImpact":{"properties":{"active_count":{"type":"integer","title":"Active Count"},"hired_count":{"type":"integer","title":"Hired Count"},"interview_count":{"type":"integer","title":"Interview Count"},"offer_reached_count":{"type":"integer","title":"Offer Reached Count"},"has_real_activity":{"type":"boolean","title":"Has Real Activity"}},"type":"object","required":["active_count","hired_count","interview_count","offer_reached_count","has_real_activity"],"title":"JobDeleteImpact","description":"Impact preview for the delete-job dialog (CEO 2026-07-11).\n\nA job with real recruitment activity (hired, interviews, or offer-reached)\nshould surface a strong warning and suggest closing instead of deleting."},"JobDeleteRequest":{"properties":{"reject_active_applications":{"type":"boolean","title":"Reject Active Applications","default":true},"candidate_action":{"type":"string","title":"Candidate Action","default":"reject_all"},"send_rejection_email":{"type":"boolean","title":"Send Rejection Email","default":false},"notify_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Notify Template Id"}},"type":"object","title":"JobDeleteRequest","description":"Request body for job deletion (optional)."},"JobDeleteResponse":{"properties":{"message":{"type":"string","title":"Message"},"rejected_count":{"type":"integer","title":"Rejected Count","default":0}},"type":"object","required":["message"],"title":"JobDeleteResponse","description":"Response after deleting a job."},"JobFieldSuggestionsResponse":{"properties":{"titles":{"items":{"type":"string"},"type":"array","title":"Titles"},"departments":{"items":{"type":"string"},"type":"array","title":"Departments"},"skills":{"items":{"type":"string"},"type":"array","title":"Skills"},"external_members":{"items":{"$ref":"#/components/schemas/ExternalTeamMemberSuggestion"},"type":"array","title":"External Members","default":[]}},"type":"object","required":["titles","departments","skills"],"title":"JobFieldSuggestionsResponse","description":"Distinct job titles, departments, and skills for autocomplete suggestions."},"JobListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"job_code":{"type":"string","title":"Job Code"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"locations":{"items":{"type":"string"},"type":"array","title":"Locations","default":[]},"employment_type":{"$ref":"#/components/schemas/EmploymentType"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"negotiable":{"type":"boolean","title":"Negotiable","default":false},"hire_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hire Type"},"status":{"$ref":"#/components/schemas/JobStatus"},"published_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published Date"},"on_hold_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"On Hold Date"},"closed_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed Date"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"candidate_count":{"type":"integer","title":"Candidate Count","default":0},"total_candidate_count":{"type":"integer","title":"Total Candidate Count","default":0},"hired_count":{"type":"integer","title":"Hired Count","default":0},"rejected_count":{"type":"integer","title":"Rejected Count","default":0},"headcount":{"type":"integer","title":"Headcount","default":1},"publish_to_career_site":{"type":"boolean","title":"Publish To Career Site","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"pipeline_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pipeline Template Id"},"can_manage":{"type":"boolean","title":"Can Manage","default":false}},"type":"object","required":["id","job_code","title","department","employment_type","required_skills","status","created_at","updated_at"],"title":"JobListResponse","description":"Simplified response for job lists."},"JobParseEnqueueResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"type":"string","title":"Status"}},"type":"object","required":["job_id","status"],"title":"JobParseEnqueueResponse","description":"Returned by the parse-* endpoints once a row is queued.\n\nFrontend polls `GET /jobs/parse/{job_id}` every 2s until status is\n`completed` or `failed`. Decouples user-facing wait from backend parse\nduration — fixes the 2026-05-07 incident where a 5-minute LLM hang\nblocked the only worker and tripped the frontend's 30s timeout."},"JobParseResponse":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"employment_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Type"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"additional_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Info"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"required_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Required Experience Years"},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"parsed_fields":{"items":{"type":"string"},"type":"array","title":"Parsed Fields","default":[]},"confidence_score":{"type":"integer","title":"Confidence Score","default":0},"source_type":{"type":"string","title":"Source Type","default":""},"source_layer":{"type":"string","title":"Source Layer","default":""},"parse_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parse Error"},"low_confidence":{"type":"boolean","title":"Low Confidence","default":false},"raw_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Content"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"}},"type":"object","title":"JobParseResponse","description":"Response from AI job description parsing."},"JobParseStatusResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"type":"string","title":"Status"},"result":{"anyOf":[{"$ref":"#/components/schemas/JobParseResponse"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["job_id","status"],"title":"JobParseStatusResponse"},"JobPipelineUpdate":{"properties":{"stages":{"items":{"$ref":"#/components/schemas/PipelineStageCreate"},"type":"array","title":"Stages"},"stage_migrations":{"anyOf":[{"items":{"$ref":"#/components/schemas/StageMigration"},"type":"array"},{"type":"null"}],"title":"Stage Migrations"}},"type":"object","required":["stages"],"title":"JobPipelineUpdate","description":"Bulk replace all stages for a job's pipeline."},"JobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"job_code":{"type":"string","title":"Job Code"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"locations":{"items":{"$ref":"#/components/schemas/LocationSummary"},"type":"array","title":"Locations","default":[]},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"employment_type":{"$ref":"#/components/schemas/EmploymentType"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"additional_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Info"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"required_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Required Experience Years"},"hiring_process":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Process"},"status":{"$ref":"#/components/schemas/JobStatus"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"negotiable":{"type":"boolean","title":"Negotiable","default":false},"headcount":{"type":"integer","title":"Headcount","default":1},"hire_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hire Type"},"required_languages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Required Languages"},"expected_hire_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expected Hire Date"},"publish_to_career_site":{"type":"boolean","title":"Publish To Career Site","default":false},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"published_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published Date"},"closed_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed Date"},"on_hold_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"On Hold Date"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"recruitment_cost_items":{"items":{"$ref":"#/components/schemas/RecruitmentCostItem-Output"},"type":"array","title":"Recruitment Cost Items","default":[]},"cost_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Currency"},"hiring_stages":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Stages"},"hiring_team_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Team Ids"},"hiring_team_external":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Team External"},"pipeline_stages":{"items":{"$ref":"#/components/schemas/PipelineStageResponse"},"type":"array","title":"Pipeline Stages","default":[]},"pipeline_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Pipeline Template Id"},"classified_skills":{"anyOf":[{"$ref":"#/components/schemas/ClassifiedSkills"},{"type":"null"}]},"ranked_skills":{"anyOf":[{"items":{"$ref":"#/components/schemas/RankedSkill"},"type":"array"},{"type":"null"}],"title":"Ranked Skills"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"hired_count":{"type":"integer","title":"Hired Count","default":0},"total_candidate_count":{"type":"integer","title":"Total Candidate Count","default":0},"can_manage":{"type":"boolean","title":"Can Manage","default":false}},"type":"object","required":["id","tenant_id","job_code","title","department","employment_type","description","requirements","benefits","required_skills","required_experience_years","status","salary_min","salary_max","salary_currency","created_by","created_at","updated_at"],"title":"JobResponse","description":"Full response schema for a job."},"JobStatus":{"type":"string","enum":["draft","open","closed","on_hold"],"title":"JobStatus","description":"Job listing status."},"JobStatusChangeRequest":{"properties":{"status":{"$ref":"#/components/schemas/JobStatus"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"reject_active_applications":{"type":"boolean","title":"Reject Active Applications","default":false},"send_rejection_email":{"type":"boolean","title":"Send Rejection Email","default":false},"notify_on_hold":{"type":"boolean","title":"Notify On Hold","default":false},"notify_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Notify Template Id"}},"type":"object","required":["status"],"title":"JobStatusChangeRequest","description":"Request to change a job's status."},"JobStatusChangeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"$ref":"#/components/schemas/JobStatus"},"previous_status":{"$ref":"#/components/schemas/JobStatus"},"publish_to_career_site":{"type":"boolean","title":"Publish To Career Site"},"auto_unpublished":{"type":"boolean","title":"Auto Unpublished","default":false},"on_hold_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"On Hold Date"},"closed_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed Date"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"rejected_count":{"type":"integer","title":"Rejected Count","default":0}},"type":"object","required":["id","status","previous_status","publish_to_career_site"],"title":"JobStatusChangeResponse","description":"Response after changing a job's status."},"JobStatusDeptCount":{"properties":{"department":{"type":"string","title":"Department"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["department","count"],"title":"JobStatusDeptCount","description":"Count of jobs for a single (status, department) pair."},"JobStatusGroup":{"properties":{"status":{"type":"string","title":"Status"},"total":{"type":"integer","title":"Total"},"departments":{"items":{"$ref":"#/components/schemas/JobStatusDeptCount"},"type":"array","title":"Departments"}},"type":"object","required":["status","total","departments"],"title":"JobStatusGroup","description":"One status column on the stacked bar (Open / Closed / On-hold)."},"JobTemplateCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"is_default":{"type":"boolean","title":"Is Default","default":false},"defaults":{"anyOf":[{"$ref":"#/components/schemas/JobTemplateDefaults"},{"type":"null"}]},"stages":{"items":{"$ref":"#/components/schemas/JobTemplateStageInput"},"type":"array","minItems":1,"title":"Stages"}},"type":"object","required":["name","stages"],"title":"JobTemplateCreate"},"JobTemplateDefaults":{"properties":{"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"employment_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Type"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"hire_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hire Type"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"salary_negotiable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Salary Negotiable"},"required_languages":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Languages"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"headcount":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Headcount"},"hiring_team_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Team Ids"},"hiring_team_external":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Team External"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"}},"type":"object","title":"JobTemplateDefaults","description":"Flat bag of default job-form field values applied on create-from-template.\n\nD3 (re-review 2026-06-27): salary min/max dropped, benefits kept (WYSIWYG).\nD4 (design-shotgun 2026-06-28): the \"Nội dung tin\" tab also carries the long\nreusable rich-text — description + requirements — so HR doesn't retype the job\nposting body each time. Keys mirror Job's field names (FE prefills the form)."},"JobTemplateListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_default":{"type":"boolean","title":"Is Default"},"job_count":{"type":"integer","title":"Job Count","default":0}},"type":"object","required":["id","name","is_default"],"title":"JobTemplateListItem","description":"Lightweight list item for the job-form dropdown (no defaults/stages — the\nfull template is fetched via GET /{id} when the user selects one)."},"JobTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"is_default":{"type":"boolean","title":"Is Default"},"defaults":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Defaults"},"stages":{"items":{"$ref":"#/components/schemas/JobTemplateStageResponse"},"type":"array","title":"Stages","default":[]},"job_count":{"type":"integer","title":"Job Count","default":0}},"type":"object","required":["id","tenant_id","name","is_default"],"title":"JobTemplateResponse"},"JobTemplateStageInput":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"stage_type":{"type":"string","maxLength":30,"title":"Stage Type"},"sort_order":{"type":"integer","minimum":0.0,"title":"Sort Order","default":0},"is_terminal":{"type":"boolean","title":"Is Terminal","default":false},"is_optional":{"type":"boolean","title":"Is Optional","default":false},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"duration_days":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Duration Days"},"duration_unit":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Duration Unit","default":"days"},"owner_role":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Owner Role"},"auto_advance_on_pass":{"type":"boolean","title":"Auto Advance On Pass","default":true},"auto_reject_on_fail":{"type":"boolean","title":"Auto Reject On Fail","default":false}},"type":"object","required":["name","stage_type"],"title":"JobTemplateStageInput","description":"A stage within a job template (create/update)."},"JobTemplateStageResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"stage_type":{"type":"string","title":"Stage Type"},"sort_order":{"type":"integer","title":"Sort Order"},"is_terminal":{"type":"boolean","title":"Is Terminal"},"is_optional":{"type":"boolean","title":"Is Optional","default":false},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"duration_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Days"},"duration_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration Unit","default":"days"},"owner_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Role"},"auto_advance_on_pass":{"type":"boolean","title":"Auto Advance On Pass","default":true},"auto_reject_on_fail":{"type":"boolean","title":"Auto Reject On Fail","default":false}},"type":"object","required":["id","name","stage_type","sort_order","is_terminal"],"title":"JobTemplateStageResponse"},"JobTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"},"defaults":{"anyOf":[{"$ref":"#/components/schemas/JobTemplateDefaults"},{"type":"null"}]},"stages":{"anyOf":[{"items":{"$ref":"#/components/schemas/JobTemplateStageInput"},"type":"array","minItems":1},{"type":"null"}],"title":"Stages"}},"type":"object","title":"JobTemplateUpdate"},"JobTrendBucket":{"properties":{"bucket":{"type":"string","format":"date","title":"Bucket"},"opened":{"type":"integer","title":"Opened"},"closed":{"type":"integer","title":"Closed"}},"type":"object","required":["bucket","opened","closed"],"title":"JobTrendBucket","description":"One time-bucket for the job trend chart (opened vs closed)."},"JobUpdate":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Title"},"department":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Department"},"locations":{"anyOf":[{"items":{"$ref":"#/components/schemas/LocationInput"},"type":"array"},{"type":"null"}],"title":"Locations"},"employment_type":{"anyOf":[{"$ref":"#/components/schemas/EmploymentType"},{"type":"null"}]},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"additional_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Info"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"required_experience_years":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Required Experience Years"},"hiring_process":{"anyOf":[{"items":{"$ref":"#/components/schemas/HiringStage"},"type":"array"},{"type":"null"}],"title":"Hiring Process"},"salary_min":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer","maximum":1000000000000.0,"minimum":0.0},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string","pattern":"^(gross|net)$"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string","pattern":"^(hourly|monthly|yearly)$"},{"type":"null"}],"title":"Salary Period"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"negotiable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Negotiable"},"headcount":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Headcount"},"hire_type":{"anyOf":[{"type":"string","pattern":"^(new_hire|replacement)$"},{"type":"null"}],"title":"Hire Type"},"required_languages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Required Languages"},"expected_hire_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expected Hire Date"},"publish_to_career_site":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Publish To Career Site"},"recruitment_cost_items":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecruitmentCostItem-Input"},"type":"array"},{"type":"null"}],"title":"Recruitment Cost Items"},"cost_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Cost Currency"},"hiring_stages":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Stages"},"hiring_team_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Team Ids"},"hiring_team_external":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Team External"}},"type":"object","title":"JobUpdate","description":"Schema for updating a job."},"JobsOverviewResponse":{"properties":{"granularity":{"type":"string","title":"Granularity"},"trend":{"items":{"$ref":"#/components/schemas/JobTrendBucket"},"type":"array","title":"Trend"},"status_by_department":{"items":{"$ref":"#/components/schemas/JobStatusGroup"},"type":"array","title":"Status By Department"},"by_employment_type":{"items":{"$ref":"#/components/schemas/JobAttributeCount"},"type":"array","title":"By Employment Type"},"by_work_setup":{"items":{"$ref":"#/components/schemas/JobAttributeCount"},"type":"array","title":"By Work Setup"},"hired_by_employment_type":{"items":{"$ref":"#/components/schemas/JobAttributeCount"},"type":"array","title":"Hired By Employment Type","default":[]}},"type":"object","required":["granularity","trend","status_by_department","by_employment_type","by_work_setup"],"title":"JobsOverviewResponse","description":"Aggregated job-level statistics for the Reports page Job Metrics group.\n\nUses \"Activity in period\" semantics: a job is included if it was created,\nclosed, or remained open at any point during [start_date, end_date]."},"JourneyAIMatch":{"properties":{"score":{"type":"integer","title":"Score"},"recommendation":{"type":"string","title":"Recommendation"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"summary_sentence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Sentence"},"confidence_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confidence Level"},"knockout_met":{"type":"integer","title":"Knockout Met","default":0},"knockout_total":{"type":"integer","title":"Knockout Total","default":0},"calculated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Calculated At"}},"type":"object","required":["score","recommendation"],"title":"JourneyAIMatch","description":"AI matching result for this application's job."},"JourneyApplicationGroup":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_title":{"type":"string","title":"Job Title"},"job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Code"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"total_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Days"},"outcome":{"$ref":"#/components/schemas/JourneyOutcome"},"stages":{"items":{"$ref":"#/components/schemas/JourneyStageNode"},"type":"array","title":"Stages","default":[]},"emails":{"items":{"$ref":"#/components/schemas/JourneyEmail"},"type":"array","title":"Emails","default":[]},"ai_match":{"anyOf":[{"$ref":"#/components/schemas/JourneyAIMatch"},{"type":"null"}]}},"type":"object","required":["application_id","job_id","job_title","started_at","outcome"],"title":"JourneyApplicationGroup","description":"Complete journey story for one job application."},"JourneyCandidateContext":{"properties":{"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"last_contacted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Contacted At"},"is_blacklisted":{"type":"boolean","title":"Is Blacklisted","default":false},"blacklist_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blacklist Reason"},"talent_pool":{"anyOf":[{"$ref":"#/components/schemas/JourneyTalentPoolContext"},{"type":"null"}]}},"type":"object","title":"JourneyCandidateContext","description":"Top-level context card for the candidate."},"JourneyEmail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"status":{"type":"string","title":"Status"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"opened_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Opened At"},"has_reply":{"type":"boolean","title":"Has Reply","default":false},"body_preview":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Preview"},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"},"replies":{"items":{"$ref":"#/components/schemas/JourneyEmailReply"},"type":"array","title":"Replies","default":[]}},"type":"object","required":["id","status","sent_at"],"title":"JourneyEmail","description":"Email sent during this application."},"JourneyEmailReply":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"body_preview":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Preview"},"intent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intent"},"received_at":{"type":"string","format":"date-time","title":"Received At"}},"type":"object","required":["id","received_at"],"title":"JourneyEmailReply","description":"A reply received for an outbound email."},"JourneyEvaluation":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"evaluator_name":{"type":"string","title":"Evaluator Name"},"evaluator_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluator Email"},"overall_rating":{"type":"integer","title":"Overall Rating"},"rating_scale":{"type":"integer","title":"Rating Scale","default":5},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"},"criteria_scores":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"weighted_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weighted Score"},"evaluated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evaluated At"},"evaluation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evaluation Type"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"shared_info":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Shared Info"}},"type":"object","required":["id","evaluator_name","overall_rating"],"title":"JourneyEvaluation","description":"Evaluation submitted at a particular stage."},"JourneyInterview":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"round_name":{"type":"string","title":"Round Name"},"round_number":{"type":"integer","title":"Round Number"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes","default":60},"status":{"type":"string","title":"Status"},"result":{"type":"string","title":"Result","default":"pending"},"interviewer_names":{"items":{"type":"string"},"type":"array","title":"Interviewer Names","default":[]},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"is_self_schedule":{"type":"boolean","title":"Is Self Schedule","default":false},"reschedule_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reschedule Reason"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"}},"type":"object","required":["id","round_name","round_number","scheduled_at","status"],"title":"JourneyInterview","description":"Interview that happened at a particular stage."},"JourneyOutcome":{"properties":{"status":{"type":"string","title":"Status"},"date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"rejection_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason Code"},"offer_accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Offer Accepted At"}},"type":"object","required":["status"],"title":"JourneyOutcome","description":"How this application ended."},"JourneyStageNode":{"properties":{"stage_name":{"type":"string","title":"Stage Name"},"stage_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Id"},"entered_at":{"type":"string","format":"date-time","title":"Entered At"},"exited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Exited At"},"duration_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Days"},"moved_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Moved By"},"interviews":{"items":{"$ref":"#/components/schemas/JourneyInterview"},"type":"array","title":"Interviews","default":[]},"evaluations":{"items":{"$ref":"#/components/schemas/JourneyEvaluation"},"type":"array","title":"Evaluations","default":[]}},"type":"object","required":["stage_name","entered_at"],"title":"JourneyStageNode","description":"A single stage in the candidate's pipeline journey."},"JourneySummary":{"properties":{"total_applications":{"type":"integer","title":"Total Applications","default":0},"active_count":{"type":"integer","title":"Active Count","default":0},"rejected_count":{"type":"integer","title":"Rejected Count","default":0},"hired_count":{"type":"integer","title":"Hired Count","default":0},"furthest_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Furthest Stage"},"best_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Best Rating"},"best_rating_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Best Rating Context"}},"type":"object","title":"JourneySummary","description":"Summary counts for the candidate's application history."},"JourneyTalentPoolContext":{"properties":{"added_date":{"type":"string","format":"date-time","title":"Added Date"},"reason":{"type":"string","title":"Reason"},"engagement_status":{"type":"string","title":"Engagement Status"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"original_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original Job Title"},"original_job_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Original Job Code"}},"type":"object","required":["added_date","reason","engagement_status"],"title":"JourneyTalentPoolContext","description":"Talent pool context for this candidate (if in pool)."},"KpiHistoryBucket":{"properties":{"period_start":{"type":"string","format":"date","title":"Period Start"},"period_end":{"type":"string","format":"date","title":"Period End"},"total_hired":{"type":"integer","title":"Total Hired"},"total_applications":{"type":"integer","title":"Total Applications"},"offer_acceptance_rate":{"type":"number","title":"Offer Acceptance Rate"}},"type":"object","required":["period_start","period_end","total_hired","total_applications","offer_acceptance_rate"],"title":"KpiHistoryBucket","description":"One past period's headline KPIs for the MoM table.\n\n``total_applications`` counts the entry cohort (in_period_entry), so it\nmatches the rest of the report's entry-axis definition. ``total_hired`` uses\nthe event axis (hired_date in bucket), same as ``compute.count_hired``."},"KpiHistoryResponse":{"properties":{"periods":{"items":{"$ref":"#/components/schemas/KpiHistoryBucket"},"type":"array","title":"Periods"}},"type":"object","required":["periods"],"title":"KpiHistoryResponse","description":"Response for GET /reports/kpi-history — N equal-length periods, newest first."},"LocationInput":{"properties":{"country_code":{"type":"string","maxLength":2,"title":"Country Code","default":"VN"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"}},"type":"object","title":"LocationInput","description":"One location for a job (create/update).\n\nSemantics:\n- `country_code` required (default 'VN').\n- `vn_province_code` optional. Leaving it null with `country_code='VN'`\n  means \"toàn quốc\" — no dedicated flag."},"LocationSummary":{"properties":{"country_code":{"type":"string","title":"Country Code"},"country_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Name"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"vn_province_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Name"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"state_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Name"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"}},"type":"object","required":["country_code"],"title":"LocationSummary","description":"One location on a job response (includes resolved display + names)."},"LoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"LoginRequest","description":"Email/password login."},"LogoutRequest":{"properties":{"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"}},"type":"object","title":"LogoutRequest","description":"Logout / revoke refresh token. ``refresh_token`` is optional — it may be\nsent as an HttpOnly cookie instead of in the body."},"MarkReadRequest":{"properties":{"notification_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Notification Ids"}},"type":"object","required":["notification_ids"],"title":"MarkReadRequest","description":"Request to mark specific notifications as read."},"MatchBatchRequest":{"properties":{"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":50,"title":"Candidate Ids"},"cv_selections":{"anyOf":[{"additionalProperties":{"type":"string","format":"uuid"},"propertyNames":{"format":"uuid"},"type":"object"},{"type":"null"}],"title":"Cv Selections"},"language":{"type":"string","enum":["vi","en"],"title":"Language","default":"vi"}},"type":"object","required":["candidate_ids"],"title":"MatchBatchRequest","description":"Request to run AI matching for selected candidates."},"MatchBatchResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"total_matched":{"type":"integer","title":"Total Matched"},"candidates":{"items":{"$ref":"#/components/schemas/MatchScoreResponse"},"type":"array","title":"Candidates"},"processing_count":{"type":"integer","title":"Processing Count","default":0}},"type":"object","required":["job_id","total_matched","candidates"],"title":"MatchBatchResponse","description":"Response from batch matching operation."},"MatchFeedbackRequest":{"properties":{"feedback":{"type":"string","enum":["good","bad"],"title":"Feedback"}},"type":"object","required":["feedback"],"title":"MatchFeedbackRequest","description":"Request to submit feedback on a match result."},"MatchScoreResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_code":{"type":"string","title":"Candidate Code"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"overall_score":{"type":"integer","title":"Overall Score"},"hard_skills_score":{"type":"integer","title":"Hard Skills Score"},"experience_relevance_score":{"type":"integer","title":"Experience Relevance Score"},"semantic_similarity_score":{"type":"integer","title":"Semantic Similarity Score","default":0,"deprecated":true},"soft_skills_score":{"type":"integer","title":"Soft Skills Score","default":0,"deprecated":true},"recommendation":{"type":"string","title":"Recommendation"},"matching_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Matching Details"},"calculated_at":{"type":"string","format":"date-time","title":"Calculated At"},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"feedback_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Feedback At"},"zero_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zero Category"},"cv_history_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cv History Id"},"scored_cv_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scored Cv Filename"}},"type":"object","required":["id","candidate_id","candidate_name","candidate_code","job_id","overall_score","hard_skills_score","experience_relevance_score","recommendation","matching_details","calculated_at"],"title":"MatchScoreResponse","description":"Single match score result for a candidate-job pair."},"MatchedCandidatesResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"candidates":{"items":{"$ref":"#/components/schemas/MatchScoreResponse"},"type":"array","title":"Candidates"},"queue_pending_count":{"type":"integer","title":"Queue Pending Count","default":0}},"type":"object","required":["job_id","total","page","page_size","total_pages","candidates"],"title":"MatchedCandidatesResponse","description":"Paginated response of matched candidates for a job."},"MatchingFeedbackCreate":{"properties":{"argument_type":{"type":"string","enum":["for","against","knockout","general"],"title":"Argument Type"},"argument_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Argument Index"},"feedback_type":{"type":"string","enum":["agree","disagree","comment"],"title":"Feedback Type"},"comment_text":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Comment Text"}},"type":"object","required":["argument_type","feedback_type"],"title":"MatchingFeedbackCreate","description":"Request to submit feedback on a matching argument."},"MeResponse":{"properties":{"user":{"$ref":"#/components/schemas/UserResponse"},"tenant":{"$ref":"#/components/schemas/TenantBriefResponse"}},"type":"object","required":["user","tenant"],"title":"MeResponse","description":"Current user + tenant info."},"MessageResponse":{"properties":{"message":{"type":"string","title":"Message"},"success":{"type":"boolean","title":"Success","default":true}},"type":"object","required":["message"],"title":"MessageResponse","description":"Simple message response."},"MetricWithDelta":{"properties":{"current":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Current"},"previous":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Previous"},"delta":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Delta"},"delta_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Pct"}},"type":"object","required":["current","previous","delta","delta_pct"],"title":"MetricWithDelta","description":"A metric value with period-over-period comparison."},"NewsletterResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"sender_name":{"type":"string","title":"Sender Name"},"sender_email":{"type":"string","title":"Sender Email"},"sender_reply_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Reply To"},"status":{"type":"string","title":"Status"},"subscribe_on_signup":{"type":"boolean","title":"Subscribe On Signup"},"visibility":{"type":"string","title":"Visibility"},"design":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Design"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","slug","sender_name","sender_email","status","subscribe_on_signup","visibility","created_at","updated_at"],"title":"NewsletterResponse","description":"Response schema for a newsletter."},"NewsletterSendDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"newsletter_id":{"type":"string","format":"uuid","title":"Newsletter Id"},"blog_post_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Blog Post Id"},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","title":"Status"},"total_recipients":{"type":"integer","title":"Total Recipients"},"sent_count":{"type":"integer","title":"Sent Count"},"opened_count":{"type":"integer","title":"Opened Count"},"bounced_count":{"type":"integer","title":"Bounced Count"},"clicked_count":{"type":"integer","title":"Clicked Count","default":0},"failed_count":{"type":"integer","title":"Failed Count","default":0},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"post_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Title"},"post_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Slug"},"failed_recipients":{"items":{"$ref":"#/components/schemas/NewsletterSendRecipientResponse"},"type":"array","title":"Failed Recipients"},"pending_count":{"type":"integer","title":"Pending Count","default":0},"feedback_up":{"type":"integer","title":"Feedback Up","default":0},"feedback_down":{"type":"integer","title":"Feedback Down","default":0}},"type":"object","required":["id","tenant_id","newsletter_id","subject","status","total_recipients","sent_count","opened_count","bounced_count","created_at","updated_at"],"title":"NewsletterSendDetailResponse","description":"Send detail — adds the post title/slug + the failed recipients list."},"NewsletterSendListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"newsletter_id":{"type":"string","format":"uuid","title":"Newsletter Id"},"blog_post_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Blog Post Id"},"subject":{"type":"string","title":"Subject"},"status":{"type":"string","title":"Status"},"total_recipients":{"type":"integer","title":"Total Recipients"},"sent_count":{"type":"integer","title":"Sent Count"},"opened_count":{"type":"integer","title":"Opened Count"},"bounced_count":{"type":"integer","title":"Bounced Count"},"clicked_count":{"type":"integer","title":"Clicked Count","default":0},"failed_count":{"type":"integer","title":"Failed Count","default":0},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"post_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Title"},"post_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Slug"}},"type":"object","required":["id","newsletter_id","subject","status","total_recipients","sent_count","opened_count","bounced_count","created_at"],"title":"NewsletterSendListResponse","description":"Lightweight newsletter send list item."},"NewsletterSendRecipientResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"newsletter_send_id":{"type":"string","format":"uuid","title":"Newsletter Send Id"},"subscriber_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Subscriber Id"},"candidate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Candidate Id"},"email":{"type":"string","title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"opened_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Opened At"},"clicked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Clicked At"},"bounced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Bounced At"}},"type":"object","required":["id","newsletter_send_id","email","status"],"title":"NewsletterSendRecipientResponse","description":"Response schema for a newsletter send recipient."},"NewsletterSendSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","title":"Status"},"total_recipients":{"type":"integer","title":"Total Recipients"},"sent_count":{"type":"integer","title":"Sent Count"},"failed_count":{"type":"integer","title":"Failed Count"},"opened_count":{"type":"integer","title":"Opened Count"},"bounced_count":{"type":"integer","title":"Bounced Count"},"clicked_count":{"type":"integer","title":"Clicked Count","default":0},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["id","status","total_recipients","sent_count","failed_count","opened_count","bounced_count"],"title":"NewsletterSendSummary","description":"Compact send status embedded in BlogPostResponse.latest_send (editor banner)."},"NewsletterSettingsUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"sender_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Sender Name"},"sender_reply_to":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Sender Reply To"}},"type":"object","title":"NewsletterSettingsUpdate","description":"Editable from /overview/blog/settings. sender_email stays read-only (v1)."},"NotificationListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/NotificationResponse"},"type":"array","title":"Items"},"unread_count":{"type":"integer","title":"Unread Count"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","unread_count","total"],"title":"NotificationListResponse","description":"Paginated notification list with unread count."},"NotificationPreferenceResponse":{"properties":{"email_enabled":{"type":"boolean","title":"Email Enabled"},"email_preferences":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Email Preferences"},"inapp_preferences":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Inapp Preferences"}},"type":"object","required":["email_enabled","email_preferences","inapp_preferences"],"title":"NotificationPreferenceResponse","description":"Response for notification preferences (in-app + email, per type)."},"NotificationPreferenceUpdate":{"properties":{"email_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Enabled"},"email_preferences":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Email Preferences"},"inapp_preferences":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Inapp Preferences"}},"type":"object","title":"NotificationPreferenceUpdate","description":"Partial update for notification preferences. Missing fields untouched."},"NotificationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"type":{"type":"string","title":"Type"},"title":{"type":"string","title":"Title"},"message":{"type":"string","title":"Message"},"is_read":{"type":"boolean","title":"Is Read"},"read_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Read At"},"entity_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"},"entity_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","type","title","message","is_read","created_at"],"title":"NotificationResponse","description":"Single notification response."},"OfferAcceptRequest":{"properties":{"accepted_at":{"type":"string","format":"date","title":"Accepted At"}},"type":"object","required":["accepted_at"],"title":"OfferAcceptRequest","description":"Recruiter marks the offer as accepted on behalf of the candidate.\n\n``accepted_at`` is required because it drives the time-to-fill metric\n(the canonical anchor is ``applications.offer_accepted_at``, populated\nfrom this field)."},"OfferAttachmentListResponse":{"properties":{"attachments":{"items":{"$ref":"#/components/schemas/OfferAttachmentResponse"},"type":"array","title":"Attachments"},"total":{"type":"integer","title":"Total"},"remaining_slots":{"type":"integer","title":"Remaining Slots"}},"type":"object","required":["attachments","total","remaining_slots"],"title":"OfferAttachmentListResponse"},"OfferAttachmentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"offer_letter_id":{"type":"string","format":"uuid","title":"Offer Letter Id"},"file_url":{"type":"string","title":"File Url"},"original_filename":{"type":"string","title":"Original Filename"},"file_size_bytes":{"type":"integer","title":"File Size Bytes"},"content_type":{"type":"string","title":"Content Type"},"uploaded_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Uploaded By"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","offer_letter_id","file_url","original_filename","file_size_bytes","content_type","uploaded_by","created_at"],"title":"OfferAttachmentResponse","description":"A single evidence file attached to an external-log offer.\n\nColumn shape mirrors CandidateAttachment. ``file_url`` is what the storage\nservice returned at upload time; the endpoint layer decides whether to\nswap it for a short-lived signed URL before responding."},"OfferCancelRequest":{"properties":{"reason_code":{"type":"string","enum":["business_decision","candidate_no_longer_eligible","other"],"title":"Reason Code"},"notes":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Notes"},"send_email":{"type":"boolean","title":"Send Email","default":true},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"}},"type":"object","required":["reason_code"],"title":"OfferCancelRequest","description":"Request body for POST /offers/{id}/cancel.\n\nCompany-side cancellation. Valid from ``pending`` and (via a separate\ntransition guard) ``accepted``. Immutable after ``cancelled``.\n\n``candidate_no_longer_eligible`` requires notes to trace *why* the company\ndecided the candidate no longer fits (background check fail, conflict of\ninterest, revoked headcount) — this is legally sensitive audit data."},"OfferDeclineReason":{"properties":{"reason":{"type":"string","title":"Reason"},"count":{"type":"integer","title":"Count"},"percentage":{"type":"number","title":"Percentage"}},"type":"object","required":["reason","count","percentage"],"title":"OfferDeclineReason","description":"Rejection reasons breakdown."},"OfferDeclineRequest":{"properties":{"reason_code":{"type":"string","enum":["compensation","role_and_job","external_factors","no_response","other"],"title":"Reason Code"},"notes":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Notes"},"response_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Response Date"}},"type":"object","required":["reason_code"],"title":"OfferDeclineRequest"},"OfferEmploymentType":{"type":"string","enum":["full_time","part_time","contractor","intern"],"title":"OfferEmploymentType"},"OfferKpisResponse":{"properties":{"offer_rate":{"$ref":"#/components/schemas/OfferRateMetric"},"acceptance_rate":{"$ref":"#/components/schemas/OfferRateMetric"}},"type":"object","required":["offer_rate","acceptance_rate"],"title":"OfferKpisResponse","description":"KPI cards for the Offer Tracking tab.\n\n- ``offer_rate``: distinct applications that received an offer (latest\n  version of offer_letters with sent_at in range) over applications past\n  the Sourcing stage created in the same window. May understate when HR\n  sends offers outside Tick Up without logging.\n- ``acceptance_rate``: accepted / (accepted + declined + cancelled) — only\n  counts offers with a resolved outcome. Pending offers and transient\n  ``withdrawn`` (retract-to-resend) offers are excluded."},"OfferLanguage":{"type":"string","enum":["vi","en","bilingual"],"title":"OfferLanguage"},"OfferLetterCreate":{"properties":{"sent_via":{"$ref":"#/components/schemas/OfferSentVia"},"job_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Department"},"job_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Description"},"report_to_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Report To Name"},"report_to_title":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Report To Title"},"employment_type":{"anyOf":[{"$ref":"#/components/schemas/OfferEmploymentType"},{"type":"null"}]},"level":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Level"},"contract_type":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Contract Type"},"working_hours":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Working Hours"},"work_location":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Work Location"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"probation_period":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Probation Period"},"gross_salary_amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Gross Salary Amount"},"gross_salary_currency":{"anyOf":[{"type":"string","maxLength":3},{"type":"null"}],"title":"Gross Salary Currency"},"gross_salary_unit":{"anyOf":[{"$ref":"#/components/schemas/OfferSalaryUnit"},{"type":"null"}]},"gross_salary_in_words":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Gross Salary In Words"},"probation_salary_amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Probation Salary Amount"},"probation_salary_in_words":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Probation Salary In Words"},"salary_type":{"anyOf":[{"type":"string","enum":["gross","net"]},{"type":"null"}],"title":"Salary Type"},"signature_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Signature Name"},"signature_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Signature Title"},"language":{"anyOf":[{"$ref":"#/components/schemas/OfferLanguage"},{"type":"null"}]},"email_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Email Template Id"},"email_subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Email Subject"},"email_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Body"},"attachment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Url"},"attachment_filename":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Attachment Filename"},"expiry_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiry Date"},"cc_emails":{"anyOf":[{"items":{"type":"string","format":"email"},"type":"array"},{"type":"null"}],"title":"Cc Emails"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"internal_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Notes"}},"type":"object","required":["sent_via","sent_at"],"title":"OfferLetterCreate","description":"Request body for POST /applications/{id}/offers."},"OfferLetterPatch":{"properties":{"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"job_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Description"},"report_to_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report To Name"},"report_to_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report To Title"},"employment_type":{"anyOf":[{"$ref":"#/components/schemas/OfferEmploymentType"},{"type":"null"}]},"level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Level"},"contract_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contract Type"},"working_hours":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Working Hours"},"work_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Location"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"probation_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Period"},"gross_salary_amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Gross Salary Amount"},"gross_salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary Currency"},"gross_salary_unit":{"anyOf":[{"$ref":"#/components/schemas/OfferSalaryUnit"},{"type":"null"}]},"gross_salary_in_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary In Words"},"probation_salary_amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Probation Salary Amount"},"probation_salary_in_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Salary In Words"},"salary_type":{"anyOf":[{"type":"string","enum":["gross","net"]},{"type":"null"}],"title":"Salary Type"},"language":{"anyOf":[{"$ref":"#/components/schemas/OfferLanguage"},{"type":"null"}]},"email_subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Subject"},"email_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Body"},"attachment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Url"},"attachment_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Filename"},"expiry_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiry Date"},"internal_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Notes"},"signature_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Name"},"signature_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Title"}},"type":"object","title":"OfferLetterPatch","description":"Partial update — only allowed when status=pending.\n\nAll fields optional. Service layer rejects fields that shouldn't change\nafter send (e.g. ``sent_via``, ``offer_number``)."},"OfferLetterResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"offer_number":{"type":"string","title":"Offer Number"},"version":{"type":"integer","title":"Version"},"status":{"$ref":"#/components/schemas/OfferStatus"},"sent_via":{"$ref":"#/components/schemas/OfferSentVia"},"company_name":{"type":"string","title":"Company Name"},"company_logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Logo Url"},"candidate_name_snapshot":{"type":"string","title":"Candidate Name Snapshot"},"candidate_email_snapshot":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email Snapshot"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"job_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Description"},"report_to_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report To Name"},"report_to_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Report To Title"},"employment_type":{"anyOf":[{"$ref":"#/components/schemas/OfferEmploymentType"},{"type":"null"}]},"level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Level"},"contract_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contract Type"},"working_hours":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Working Hours"},"work_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Location"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"probation_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Period"},"gross_salary_amount":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Gross Salary Amount"},"gross_salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary Currency"},"gross_salary_unit":{"anyOf":[{"$ref":"#/components/schemas/OfferSalaryUnit"},{"type":"null"}]},"gross_salary_in_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gross Salary In Words"},"probation_salary_amount":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Probation Salary Amount"},"probation_salary_in_words":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Salary In Words"},"salary_type":{"anyOf":[{"type":"string","enum":["gross","net"]},{"type":"null"}],"title":"Salary Type"},"signature_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Name"},"signature_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Title"},"language":{"anyOf":[{"$ref":"#/components/schemas/OfferLanguage"},{"type":"null"}]},"email_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Email Template Id"},"email_subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Subject"},"email_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Body"},"cc_emails":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Cc Emails"},"attachment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Url"},"attachment_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Filename"},"expiry_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiry Date"},"reminder_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reminder Sent At"},"internal_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Notes"},"decline_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Reason Code"},"decline_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Notes"},"cancel_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason Code"},"cancel_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Notes"},"withdraw_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Withdraw Reason"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Responded At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"redacted":{"type":"boolean","title":"Redacted","default":false},"suggested_application_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggested Application Action"},"current_application_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Application Status"},"current_job_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Status"},"current_job_close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Close Reason"}},"type":"object","required":["id","application_id","offer_number","version","status","sent_via","company_name","company_logo_url","candidate_name_snapshot","candidate_email_snapshot","job_title","department","job_description","report_to_name","report_to_title","employment_type","level","contract_type","working_hours","work_location","start_date","probation_period","gross_salary_amount","gross_salary_currency","gross_salary_unit","gross_salary_in_words","probation_salary_amount","probation_salary_in_words","salary_type","signature_name","signature_title","language","email_template_id","email_subject","email_body","attachment_url","attachment_filename","expiry_date","reminder_sent_at","internal_notes","decline_reason_code","decline_notes","cancel_reason_code","cancel_notes","withdraw_reason","sent_at","responded_at","created_at","updated_at","created_by"],"title":"OfferLetterResponse","description":"Full offer letter representation returned to the FE."},"OfferListItem":{"properties":{"application_id":{"type":"string","title":"Application Id"},"offer_id":{"type":"string","title":"Offer Id"},"candidate_id":{"type":"string","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"},"job_id":{"type":"string","title":"Job Id"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"line_manager":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line Manager"},"sent_at":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Sent At"},"status":{"type":"string","title":"Status"},"responded_at":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Responded At"},"decline_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Reason Code"},"decline_reason_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Reason Label"},"decline_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decline Notes"},"cancel_reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason Code"},"cancel_reason_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Reason Label"},"cancel_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancel Notes"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"probation_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Probation Period"}},"type":"object","required":["application_id","offer_id","candidate_id","candidate_name","job_id","status"],"title":"OfferListItem","description":"A single offer row for the Offer Tracking table.\n\nColumn-only payload (no relationships) — safe to serialize. One row per\napplication, showing the LATEST version of the offer letter. Snapshots\n(job_title, department, line_manager, candidate_name) come from the offer\nletter itself so the row reflects what was offered, not current Job state."},"OfferListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OfferListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"OfferListResponse","description":"Paginated offer list response."},"OfferPostponeHistoryResponse":{"properties":{"offer_id":{"type":"string","format":"uuid","title":"Offer Id"},"current_start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Current Start Date"},"changes":{"items":{"$ref":"#/components/schemas/OfferStartDateChangeResponse"},"type":"array","title":"Changes"}},"type":"object","required":["offer_id","current_start_date","changes"],"title":"OfferPostponeHistoryResponse"},"OfferPostponeRequest":{"properties":{"new_start_date":{"type":"string","format":"date","title":"New Start Date"},"reason_note":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Reason Note"}},"type":"object","required":["new_start_date"],"title":"OfferPostponeRequest","description":"HR pushes an accepted offer's start_date to a later date.\n\n``reason_note`` is optional per spec but always logged (single source of\ntruth for the postpone history feed on the OfferCard)."},"OfferPreFillData":{"properties":{"company_name":{"type":"string","title":"Company Name"},"company_logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Logo Url"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"},"job_title":{"type":"string","title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"job_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Description"},"employment_type":{"anyOf":[{"$ref":"#/components/schemas/OfferEmploymentType"},{"type":"null"}]},"work_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Location"},"available_locations":{"items":{"type":"string"},"type":"array","title":"Available Locations","default":[]}},"type":"object","required":["company_name","company_logo_url","candidate_name","candidate_email","job_title","department","job_description","employment_type","work_location"],"title":"OfferPreFillData","description":"Data the FE uses to pre-fill the SendOfferDialog form.\n\nPulls from the application's job + candidate + tenant. Recruiter can\noverride anything before submitting."},"OfferRateMetric":{"properties":{"numerator":{"type":"integer","title":"Numerator"},"denominator":{"type":"integer","title":"Denominator"},"ratio":{"type":"number","title":"Ratio"}},"type":"object","required":["numerator","denominator","ratio"],"title":"OfferRateMetric","description":"A ratio metric with numerator / denominator."},"OfferReviseResultRequest":{"properties":{"result":{"type":"string","enum":["accepted","declined"],"title":"Result"},"response_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Response Date"},"reason_code":{"anyOf":[{"type":"string","enum":["compensation","role_and_job","external_factors","no_response","other"]},{"type":"null"}],"title":"Reason Code"},"notes":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Notes"}},"type":"object","required":["result"],"title":"OfferReviseResultRequest","description":"Recruiter logs (or re-logs) the candidate's response to an offer.\n\nEndpoint: ``POST /offers/{id}/revise-result``. Valid for both\n``sent_via='external'`` and ``sent_via='app'`` offers (Track B,\n2026-07-18). Unlike ``/accept`` and ``/decline`` (which only accept\npending), this allows ``accepted ↔ declined`` flips so HR can correct a\nlogged result when the candidate changes their mind.\n\n``response_date`` is optional recruiter input (may be in the past). When\nprovided it persists as ``offer.responded_at``; when omitted the existing\n``responded_at`` is preserved (opt-in overwrite from the FE cascade\ndialog)."},"OfferSalaryUnit":{"type":"string","enum":["month","hour"],"title":"OfferSalaryUnit"},"OfferSentVia":{"type":"string","enum":["app","external"],"title":"OfferSentVia"},"OfferStartDateChangeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"offer_id":{"type":"string","format":"uuid","title":"Offer Id"},"old_start_date":{"type":"string","format":"date","title":"Old Start Date"},"new_start_date":{"type":"string","format":"date","title":"New Start Date"},"reason_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason Note"},"changed_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Changed By"},"changed_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Changed By Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","offer_id","old_start_date","new_start_date","reason_note","changed_by","created_at"],"title":"OfferStartDateChangeResponse"},"OfferStatus":{"type":"string","enum":["pending","accepted","declined","cancelled","withdrawn"],"title":"OfferStatus"},"OfferWithdrawRequest":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"OfferWithdrawRequest"},"OnboardingCompleteRequest":{"properties":{"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action","description":"Chosen quick-start action: 'career-page', 'upload-cv', 'create-job', or null for dashboard"}},"type":"object","title":"OnboardingCompleteRequest","description":"Complete onboarding with chosen quick-start action."},"OnboardingCompleteResponse":{"properties":{"redirect_path":{"type":"string","title":"Redirect Path"}},"type":"object","required":["redirect_path"],"title":"OnboardingCompleteResponse","description":"Response after completing onboarding."},"OnboardingStatusResponse":{"properties":{"onboarding_completed":{"type":"boolean","title":"Onboarding Completed"},"onboarding_step":{"type":"integer","title":"Onboarding Step"},"full_name":{"type":"string","title":"Full Name"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"company_name":{"type":"string","title":"Company Name"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"company_size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Size"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"monthly_candidate_volume":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Monthly Candidate Volume"},"hiring_challenges":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Challenges"}},"type":"object","required":["onboarding_completed","onboarding_step","full_name","company_name"],"title":"OnboardingStatusResponse","description":"Current onboarding state + pre-filled data."},"OutlookConnectedResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"calendar_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Email"},"account_type":{"type":"string","title":"Account Type"}},"type":"object","required":["success","account_type"],"title":"OutlookConnectedResponse"},"OverviewKPIs":{"properties":{"open_jobs":{"type":"integer","title":"Open Jobs","default":0},"in_pipeline":{"type":"integer","title":"In Pipeline","default":0},"new_this_week":{"type":"integer","title":"New This Week","default":0},"hires_this_month":{"type":"integer","title":"Hires This Month","default":0}},"type":"object","title":"OverviewKPIs"},"OverviewResponse":{"properties":{"kpis":{"$ref":"#/components/schemas/OverviewKPIs"},"actions":{"$ref":"#/components/schemas/ActionsSummary"},"upcoming_interviews":{"items":{"$ref":"#/components/schemas/UpcomingInterview"},"type":"array","title":"Upcoming Interviews","default":[]},"upcoming_offers":{"items":{"$ref":"#/components/schemas/UpcomingOffer"},"type":"array","title":"Upcoming Offers","default":[]},"stale_candidates":{"items":{"$ref":"#/components/schemas/StaleCandidate"},"type":"array","title":"Stale Candidates","default":[]},"jobs_attention":{"items":{"$ref":"#/components/schemas/JobAttention"},"type":"array","title":"Jobs Attention","default":[]},"recent_activities":{"items":{"$ref":"#/components/schemas/RecentActivity"},"type":"array","title":"Recent Activities","default":[]},"has_match_scores":{"type":"boolean","title":"Has Match Scores","default":false}},"type":"object","required":["kpis","actions"],"title":"OverviewResponse"},"PageStatus":{"type":"string","enum":["draft","published","archived"],"title":"PageStatus","description":"Page publication status."},"PageType":{"type":"string","enum":["career_home","about_us","culture","benefits","team","custom"],"title":"PageType","description":"Types of company pages."},"PageVersionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"version_number":{"type":"integer","title":"Version Number"},"change_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change Summary"},"is_published_version":{"type":"boolean","title":"Is Published Version"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"content":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content"}},"type":"object","required":["id","version_number","change_summary","is_published_version","created_at"],"title":"PageVersionResponse","description":"Response schema for page version."},"PaginatedResponse_ActionAuditLogResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ActionAuditLogResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[ActionAuditLogResponse]"},"PaginatedResponse_ApplicationWithCandidateResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ApplicationWithCandidateResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[ApplicationWithCandidateResponse]"},"PaginatedResponse_CandidateAccessLogResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CandidateAccessLogResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[CandidateAccessLogResponse]"},"PaginatedResponse_CandidateListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CandidateListResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[CandidateListResponse]"},"PaginatedResponse_CompanyPageListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CompanyPageListResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[CompanyPageListResponse]"},"PaginatedResponse_EnrollmentResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/EnrollmentResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[EnrollmentResponse]"},"PaginatedResponse_JobListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/JobListResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[JobListResponse]"},"PaginatedResponse_SequenceResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SequenceResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[SequenceResponse]"},"PaginatedResponse_TalentPoolCandidateResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TalentPoolCandidateResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"}},"type":"object","required":["items","total","page","page_size","total_pages"],"title":"PaginatedResponse[TalentPoolCandidateResponse]"},"ParseTextRequest":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"ParseTextRequest"},"ParseUrlRequest":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"ParseUrlRequest"},"PendingHireItem":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Department"},"offer_id":{"type":"string","format":"uuid","title":"Offer Id"},"start_date":{"type":"string","format":"date","title":"Start Date"},"offer_created_at":{"type":"string","format":"date","title":"Offer Created At"}},"type":"object","required":["application_id","candidate_id","candidate_name","job_id","offer_id","start_date","offer_created_at"],"title":"PendingHireItem","description":"Offer đã accepted + start_date đã tới, chờ HR confirm hired/no-show.\nScoped theo người tạo offer (mirror cron fan-out policy)."},"PipelineSnapshotSlice":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"count":{"type":"integer","title":"Count"},"kind":{"type":"string","enum":["stage","hired","rejected"],"title":"Kind"}},"type":"object","required":["key","label","count","kind"],"title":"PipelineSnapshotSlice","description":"One slice of the realtime pipeline snapshot donut.\n\nA REALTIME (not period-bound) count of eligible applications, sliced by\ncurrent state: each ACTIVE funnel stage as its own ``kind='stage'`` slice\nplus terminal ``kind='hired'`` / ``kind='rejected'`` slices. The FE computes\npercentages from the counts. Ordered active-stages-in-chain-order, then\ncustom stage names by count desc, then hired, then rejected last."},"PipelineStageCreate":{"properties":{"id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Id"},"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"stage_type":{"type":"string","maxLength":30,"title":"Stage Type"},"sort_order":{"type":"integer","minimum":0.0,"title":"Sort Order","default":0},"is_terminal":{"type":"boolean","title":"Is Terminal","default":false},"is_optional":{"type":"boolean","title":"Is Optional","default":false},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"duration_days":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Duration Days"},"duration_unit":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Duration Unit","default":"days"},"owner_role":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Owner Role"}},"type":"object","required":["name","stage_type"],"title":"PipelineStageCreate","description":"Schema for creating a pipeline stage.\n\n``id`` is read ONLY by the bulk ``PUT /{job_id}/pipeline`` upsert — to match\nan existing stage and update it in place (preserving its UUID and every FK).\nThe single-stage ``POST`` ignores it and server-generates the id."},"PipelineStageResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"stage_type":{"type":"string","title":"Stage Type"},"sort_order":{"type":"integer","title":"Sort Order"},"is_terminal":{"type":"boolean","title":"Is Terminal"},"is_optional":{"type":"boolean","title":"Is Optional","default":false},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"duration_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Days"},"duration_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration Unit","default":"days"},"owner_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Role"},"template_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Stage Id"}},"type":"object","required":["id","job_id","tenant_id","name","stage_type","sort_order","is_terminal"],"title":"PipelineStageResponse","description":"Response schema for a pipeline stage."},"PipelineStageUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"stage_type":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Stage Type"},"sort_order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Sort Order"},"is_terminal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Terminal"},"is_optional":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Optional"},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"duration_days":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Duration Days"},"duration_unit":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Duration Unit"},"owner_role":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Owner Role"}},"type":"object","title":"PipelineStageUpdate","description":"Schema for updating a pipeline stage."},"PreParseCvResponse":{"properties":{"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},"type":"object","title":"PreParseCvResponse"},"ProviderStatus":{"properties":{"connected":{"type":"boolean","title":"Connected"},"calendar_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calendar Email"},"account_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Type"}},"type":"object","required":["connected"],"title":"ProviderStatus"},"PublicBatchCandidate":{"properties":{"evaluation_id":{"type":"string","title":"Evaluation Id"},"application_id":{"type":"string","title":"Application Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Code"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"applied_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied Date"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"note_from_recruiter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note From Recruiter"},"attachments":{"items":{"$ref":"#/components/schemas/SharedAttachment"},"type":"array","title":"Attachments"},"links":{"items":{"$ref":"#/components/schemas/SharedLink"},"type":"array","title":"Links"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"experience_summary":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Experience Summary"},"education_summary":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Education Summary"},"expected_salary":{"anyOf":[{"$ref":"#/components/schemas/SharedExpectedSalary"},{"type":"null"}]},"matching_score":{"anyOf":[{"$ref":"#/components/schemas/SharedMatchingScore"},{"type":"null"}]},"hr_review":{"anyOf":[{"$ref":"#/components/schemas/SharedHRReview"},{"type":"null"}]},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"is_finalized":{"type":"boolean","title":"Is Finalized","default":false}},"type":"object","required":["evaluation_id","application_id","candidate_name"],"title":"PublicBatchCandidate","description":"One candidate in a batch review context (public)."},"PublicBatchHMReviewContext":{"properties":{"reviewer_name":{"type":"string","title":"Reviewer Name"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"note_from_recruiter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note From Recruiter"},"deadline_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deadline At"},"candidates":{"items":{"$ref":"#/components/schemas/PublicBatchCandidate"},"type":"array","title":"Candidates"},"decided_count":{"type":"integer","title":"Decided Count","default":0},"total_count":{"type":"integer","title":"Total Count","default":0},"all_decided":{"type":"boolean","title":"All Decided","default":false},"is_submitted":{"type":"boolean","title":"Is Submitted","default":false}},"type":"object","required":["reviewer_name"],"title":"PublicBatchHMReviewContext","description":"Context for the batch HM review page (public, token-based)."},"PublicBlogPostDetail":{"properties":{"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"content_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Html"},"feature_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feature Image Url"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"locale":{"type":"string","title":"Locale"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"meta":{"anyOf":[{"$ref":"#/components/schemas/BlogPostMeta"},{"type":"null"}]},"tags":{"items":{"$ref":"#/components/schemas/PublicBlogTag"},"type":"array","title":"Tags"}},"type":"object","required":["slug","title","updated_at","locale"],"title":"PublicBlogPostDetail","description":"Public single-post response — full rendered web HTML + SEO meta."},"PublicBlogPostList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PublicBlogPostListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["items","total","limit","offset"],"title":"PublicBlogPostList","description":"Paginated public list response."},"PublicBlogPostListItem":{"properties":{"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"},"feature_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feature Image Url"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"locale":{"type":"string","title":"Locale"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"tags":{"items":{"$ref":"#/components/schemas/PublicBlogTag"},"type":"array","title":"Tags"}},"type":"object","required":["slug","title","locale"],"title":"PublicBlogPostListItem","description":"Public list item — newest-first card data, no heavy HTML payload."},"PublicBlogTag":{"properties":{"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"}},"type":"object","required":["name","slug"],"title":"PublicBlogTag","description":"A tag as exposed on the public blog (name + slug only)."},"PublicCandidateDetailResponse":{"properties":{"candidate":{"additionalProperties":true,"type":"object","title":"Candidate"},"application":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Application"},"interview":{"additionalProperties":true,"type":"object","title":"Interview"}},"type":"object","required":["candidate","interview"],"title":"PublicCandidateDetailResponse","description":"Full candidate data for interviewers accessing via token."},"PublicCandidateProfile":{"properties":{"candidate_name":{"type":"string","title":"Candidate Name"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"skills":{"items":{"type":"string"},"type":"array","title":"Skills","default":[]},"job_title":{"type":"string","title":"Job Title"},"interview_round":{"type":"string","title":"Interview Round"},"scheduled_at":{"type":"string","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"}},"type":"object","required":["candidate_name","job_title","interview_round","scheduled_at","duration_minutes"],"title":"PublicCandidateProfile","description":"Read-only candidate summary for interviewers. No email/phone for privacy."},"PublicFeedbackContext":{"properties":{"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"interview_round":{"type":"string","title":"Interview Round"},"scheduled_at":{"type":"string","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"interviewer_name":{"type":"string","title":"Interviewer Name"},"has_submitted":{"type":"boolean","title":"Has Submitted","default":false},"submitted":{"anyOf":[{"$ref":"#/components/schemas/PublicFeedbackSubmission"},{"type":"null"}]},"evaluation_form":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evaluation Form"}},"type":"object","required":["candidate_name","job_title","interview_round","scheduled_at","duration_minutes","interviewer_name"],"title":"PublicFeedbackContext","description":"Interview context for the feedback form."},"PublicFeedbackResponse":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"type":"string","title":"Message","default":"Feedback submitted successfully"}},"type":"object","title":"PublicFeedbackResponse","description":"Response after submitting feedback."},"PublicFeedbackSubmission":{"properties":{"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"rating_scale":{"type":"integer","title":"Rating Scale","default":5},"criteria_scores":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"feedback":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"submitted_at":{"type":"string","title":"Submitted At"}},"type":"object","required":["submitted_at"],"title":"PublicFeedbackSubmission","description":"Snapshot of a previously submitted feedback (readonly view when re-opening).\n\nPopulated only when the interviewer has already submitted. Sourced from the\ncanonical Evaluation row (evaluation_type='interview_feedback') and falls\nback to interview.feedback_data.submissions[] if the Evaluation insert\nfailed at submit time (see submit_feedback savepoint)."},"PublicFeedbackSubmit":{"properties":{"rating":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Rating"},"technical_skills":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Technical Skills"},"communication":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Communication"},"culture_fit":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Culture Fit"},"criteria_scores":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Criteria Scores"},"feedback":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Feedback"},"result":{"type":"string","pattern":"^(strong_hire|hire|no_hire|passed|failed|not_passed|neutral|pending)$","title":"Result"}},"type":"object","required":["result"],"title":"PublicFeedbackSubmit","description":"Feedback submission from an external interviewer.\n\n`rating`, `technical_skills`, `communication`, `culture_fit`, and\n`feedback` are nullable since migration 193 (template.has_score / has_notes\noff → interviewer submits without those fields). `result` remains\nrequired because Result is the one section a template can never disable."},"PublicHMReviewContext":{"properties":{"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Code"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"job_title":{"type":"string","title":"Job Title"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"note_from_recruiter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note From Recruiter"},"has_decided":{"type":"boolean","title":"Has Decided","default":false},"decided_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decided Result"},"decided_comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decided Comment"},"attachments":{"items":{"$ref":"#/components/schemas/SharedAttachment"},"type":"array","title":"Attachments"},"links":{"items":{"$ref":"#/components/schemas/SharedLink"},"type":"array","title":"Links"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"experience_summary":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Experience Summary"},"education_summary":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Education Summary"},"expected_salary":{"anyOf":[{"$ref":"#/components/schemas/SharedExpectedSalary"},{"type":"null"}]},"matching_score":{"anyOf":[{"$ref":"#/components/schemas/SharedMatchingScore"},{"type":"null"}]},"hr_review":{"anyOf":[{"$ref":"#/components/schemas/SharedHRReview"},{"type":"null"}]}},"type":"object","required":["candidate_name","job_title"],"title":"PublicHMReviewContext","description":"Context for the HM review page (public, token-based)."},"PublicHMReviewDecisionResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"type":"string","title":"Message","default":"Decision submitted successfully"}},"type":"object","title":"PublicHMReviewDecisionResult","description":"Response after submitting a decision."},"PublicHMReviewDecisionSubmit":{"properties":{"decision":{"type":"string","pattern":"^(passed|not_passed)$","title":"Decision"},"comment":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Comment"}},"type":"object","required":["decision"],"title":"PublicHMReviewDecisionSubmit","description":"Decision submission from a Hiring Manager."},"PublicInterviewResponseContext":{"properties":{"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"interview_round":{"type":"string","title":"Interview Round"},"scheduled_at":{"type":"string","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewer_names":{"items":{"type":"string"},"type":"array","title":"Interviewer Names","default":[]},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"has_responded":{"type":"boolean","title":"Has Responded","default":false},"current_response":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Response"}},"type":"object","required":["candidate_name","job_title","interview_round","scheduled_at","duration_minutes"],"title":"PublicInterviewResponseContext","description":"Interview context for the candidate accept/decline page."},"PublicInterviewResponseResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"type":"string","title":"Message","default":"Response submitted successfully"}},"type":"object","title":"PublicInterviewResponseResult","description":"Response after submitting accept/decline."},"PublicInterviewResponseSubmit":{"properties":{"action":{"type":"string","pattern":"^(accept|decline)$","title":"Action"},"decline_reason":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Decline Reason"},"suggested_times":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Suggested Times"}},"type":"object","required":["action"],"title":"PublicInterviewResponseSubmit","description":"Candidate's accept/decline response."},"PublicInterviewerResponseContext":{"properties":{"interviewer_name":{"type":"string","title":"Interviewer Name"},"interviewer_email":{"type":"string","title":"Interviewer Email"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"interview_round":{"type":"string","title":"Interview Round"},"scheduled_at":{"type":"string","title":"Scheduled At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"has_responded":{"type":"boolean","title":"Has Responded","default":false},"current_response":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Response"}},"type":"object","required":["interviewer_name","interviewer_email","candidate_name","job_title","interview_round","scheduled_at","duration_minutes"],"title":"PublicInterviewerResponseContext","description":"Interview context for the interviewer accept/decline page."},"PublicInterviewerResponseResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"type":"string","title":"Message","default":"Response submitted successfully"}},"type":"object","title":"PublicInterviewerResponseResult","description":"Response after submitting interviewer accept/decline."},"PublicInterviewerResponseSubmit":{"properties":{"action":{"type":"string","pattern":"^(accept|decline)$","title":"Action"},"decline_reason":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Decline Reason"}},"type":"object","required":["action"],"title":"PublicInterviewerResponseSubmit","description":"Interviewer's accept/decline response."},"PublicJobDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"job_code":{"type":"string","title":"Job Code"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"employment_type":{"$ref":"#/components/schemas/EmploymentType"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"additional_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Info"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"required_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Required Experience Years"},"required_languages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Required Languages"},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"negotiable":{"type":"boolean","title":"Negotiable","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"hiring_process":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Hiring Process"}},"type":"object","required":["id","job_code","title","department","employment_type","description","requirements","benefits","additional_info","required_skills","required_experience_years","salary_min","salary_max","salary_currency","created_at"],"title":"PublicJobDetailResponse","description":"Full public job detail response for job detail page."},"PublicJobFiltersResponse":{"properties":{"departments":{"items":{"type":"string"},"type":"array","title":"Departments"},"locations":{"items":{"type":"string"},"type":"array","title":"Locations"},"employment_types":{"items":{"type":"string"},"type":"array","title":"Employment Types"},"work_setups":{"items":{"type":"string"},"type":"array","title":"Work Setups","default":[]}},"type":"object","required":["departments","locations","employment_types"],"title":"PublicJobFiltersResponse","description":"Distinct filter values from open jobs."},"PublicJobPaginatedResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PublicJobResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"PublicJobPaginatedResponse","description":"Paginated response for public job listings."},"PublicJobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"employment_type":{"$ref":"#/components/schemas/EmploymentType"},"work_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Setup"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"requirements":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requirements"},"benefits":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Benefits"},"required_skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Skills"},"salary_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Min"},"salary_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Salary Max"},"salary_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Currency"},"salary_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Type"},"salary_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Salary Period"},"negotiable":{"type":"boolean","title":"Negotiable","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","title","department","employment_type","description","required_skills","salary_min","salary_max","salary_currency","created_at"],"title":"PublicJobResponse","description":"Public-safe job response (no internal IDs)."},"PublicPageResponse":{"properties":{"title":{"type":"string","title":"Title"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"meta_keywords":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Meta Keywords"},"og_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Og Image Url"},"content":{"additionalProperties":true,"type":"object","title":"Content"},"settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Settings"},"company_name":{"type":"string","title":"Company Name"},"company_logo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Logo"},"tenant_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant Code"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"show_powered_badge":{"type":"boolean","title":"Show Powered Badge","default":true}},"type":"object","required":["title","content","company_name"],"title":"PublicPageResponse","description":"Response for a public page view."},"PublicSelfScheduleContext":{"properties":{"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"interview_round":{"type":"string","title":"Interview Round"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewer_names":{"items":{"type":"string"},"type":"array","title":"Interviewer Names","default":[]},"agenda":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agenda"},"slots":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Slots","default":[]},"has_selected":{"type":"boolean","title":"Has Selected","default":false},"selected_slot_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Slot Id"}},"type":"object","required":["candidate_name","job_title","interview_round","duration_minutes"],"title":"PublicSelfScheduleContext","description":"Context for the candidate self-scheduling page."},"PublicSelfScheduleResult":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"type":"string","title":"Message","default":"Interview scheduled successfully"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"}},"type":"object","title":"PublicSelfScheduleResult","description":"Response after candidate selects a slot."},"PublicSelfScheduleSelect":{"properties":{"slot_id":{"type":"string","format":"uuid","title":"Slot Id"}},"type":"object","required":["slot_id"],"title":"PublicSelfScheduleSelect","description":"Candidate's slot selection."},"PublishRequest":{"properties":{"send_newsletter":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Send Newsletter"},"subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Subject"}},"type":"object","title":"PublishRequest","description":"Body of POST /blog/posts/{id}/publish (optional; empty = plain publish).\n\n``send_newsletter`` is deliberately THREE-valued: ``None`` = the caller said\nnothing about the newsletter (the list page's Publish button), ``False`` =\nthe caller actively switched it off. Collapsing the two made a plain publish\nwipe a scheduled post's newsletter toggle (A1)."},"PublishResponse":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"published_at":{"type":"string","format":"date-time","title":"Published At"},"version_number":{"type":"integer","title":"Version Number"},"public_url":{"type":"string","title":"Public Url"}},"type":"object","required":["published_at","version_number","public_url"],"title":"PublishResponse","description":"Response after publishing a page."},"QueryBreakdown":{"properties":{"platform":{"type":"string","title":"Platform"},"role":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdownCategory"},{"type":"null"}]},"seniority":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdownCategory"},{"type":"null"}]},"industry":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdownCategory"},{"type":"null"}]},"extra_modifiers":{"items":{"type":"string"},"type":"array","title":"Extra Modifiers","default":[]},"location":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdownCategory"},{"type":"null"}]},"experience_expansion":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdownCategory"},{"type":"null"}]}},"type":"object","required":["platform"],"title":"QueryBreakdown","description":"Structured decomposition of an X-ray query for the UI Query Analyzer."},"QueryBreakdownCategory":{"properties":{"primary":{"type":"string","title":"Primary"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases"}},"type":"object","required":["primary","aliases"],"title":"QueryBreakdownCategory","description":"One expanded category in the Query Analyzer UI (role / seniority / etc.)."},"RankedSkill":{"properties":{"skill":{"type":"string","title":"Skill"},"score":{"type":"number","title":"Score"},"priority":{"type":"string","enum":["core_suggested","signal"],"title":"Priority","default":"signal"},"is_must_have_ai":{"type":"boolean","title":"Is Must Have Ai","default":false}},"type":"object","required":["skill","score"],"title":"RankedSkill","description":"A single skill ranked by importance for X-ray Core Skills Picker.\n\nProduced by ``app.services.skill_ranker.rank_skills`` — pure regex +\ncached AI matching signals, no LLM call."},"RatingRequest":{"properties":{"star_rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Star Rating"}},"type":"object","title":"RatingRequest","description":"Set or clear a candidate's star rating (1-5, or null to clear)."},"RecentActivity":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"type":{"type":"string","title":"Type"},"description":{"type":"string","title":"Description"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Candidate Id"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["id","type","description","timestamp"],"title":"RecentActivity"},"RecentApplication":{"properties":{"id":{"type":"string","title":"Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"stage":{"type":"string","title":"Stage"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Applied Date"}},"type":"object","required":["id","candidate_name","job_title","stage"],"title":"RecentApplication"},"RecentCandidate":{"properties":{"id":{"type":"string","title":"Id"},"full_name":{"type":"string","title":"Full Name"},"candidate_code":{"type":"string","title":"Candidate Code"},"source":{"type":"string","title":"Source"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","full_name","candidate_code","source","created_at"],"title":"RecentCandidate"},"RecipientCountResponse":{"properties":{"count":{"type":"integer","title":"Count"}},"type":"object","required":["count"],"title":"RecipientCountResponse"},"RecruiterPerformance":{"properties":{"recruiter_id":{"type":"string","title":"Recruiter Id"},"recruiter_name":{"type":"string","title":"Recruiter Name"},"total_applications":{"type":"integer","title":"Total Applications"},"hires_count":{"type":"integer","title":"Hires Count"},"avg_days_to_hire":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Days To Hire"}},"type":"object","required":["recruiter_id","recruiter_name","total_applications","hires_count","avg_days_to_hire"],"title":"RecruiterPerformance","description":"Performance data for a single recruiter."},"RecruitmentCostItem-Input":{"properties":{"category":{"type":"string","maxLength":100,"minLength":1,"title":"Category"},"amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Amount"},"incurred_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Incurred On"}},"type":"object","required":["category","amount"],"title":"RecruitmentCostItem","description":"One line item in a job's recruitment cost breakdown.\n\nFree-form category string (FE surfaces a preset dropdown of common\nVietnamese job boards + 'Other' for freetext). Amount uses Decimal to\npreserve precision on VND-scale integers. Date is optional — user may\nnot remember when a fee was paid."},"RecruitmentCostItem-Output":{"properties":{"category":{"type":"string","maxLength":100,"minLength":1,"title":"Category"},"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Amount"},"incurred_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Incurred On"}},"type":"object","required":["category","amount"],"title":"RecruitmentCostItem","description":"One line item in a job's recruitment cost breakdown.\n\nFree-form category string (FE surfaces a preset dropdown of common\nVietnamese job boards + 'Other' for freetext). Amount uses Decimal to\npreserve precision on VND-scale integers. Date is optional — user may\nnot remember when a fee was paid."},"RefreshRequest":{"properties":{"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"}},"type":"object","title":"RefreshRequest","description":"Token refresh. ``refresh_token`` is optional because it may instead be\nsent as an HttpOnly cookie (the body field is kept for backward-compat)."},"RegisterRequest":{"properties":{"company_name":{"type":"string","maxLength":255,"minLength":2,"title":"Company Name"},"full_name":{"type":"string","maxLength":255,"minLength":2,"title":"Full Name"},"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"},"phone":{"type":"string","maxLength":50,"title":"Phone"},"preferred_locale":{"anyOf":[{"type":"string","enum":["vi","en"]},{"type":"null"}],"title":"Preferred Locale"}},"type":"object","required":["company_name","full_name","email","password","phone"],"title":"RegisterRequest","description":"Self-signup: creates a new tenant + admin user."},"RemoveApplicationRequest":{"properties":{"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"type":"object","title":"RemoveApplicationRequest","description":"Silent removal of an application from a job — no log, no email."},"ReportResponse":{"properties":{"period_start":{"type":"string","format":"date","title":"Period Start"},"period_end":{"type":"string","format":"date","title":"Period End"},"previous_period_start":{"type":"string","format":"date","title":"Previous Period Start"},"previous_period_end":{"type":"string","format":"date","title":"Previous Period End"},"total_jobs":{"$ref":"#/components/schemas/MetricWithDelta"},"active_candidates":{"$ref":"#/components/schemas/MetricWithDelta"},"total_hired":{"$ref":"#/components/schemas/MetricWithDelta"},"avg_time_to_hire_days":{"$ref":"#/components/schemas/MetricWithDelta"},"offer_acceptance_rate":{"$ref":"#/components/schemas/MetricWithDelta"},"candidates_by_stage":{"items":{"$ref":"#/components/schemas/StageCount"},"type":"array","title":"Candidates By Stage"},"conversion_rates":{"items":{"$ref":"#/components/schemas/ConversionRate"},"type":"array","title":"Conversion Rates"},"source_effectiveness":{"items":{"$ref":"#/components/schemas/SourceEffectiveness"},"type":"array","title":"Source Effectiveness"},"top_performing_jobs":{"items":{"$ref":"#/components/schemas/TopJob"},"type":"array","title":"Top Performing Jobs"},"recruiter_performance":{"items":{"$ref":"#/components/schemas/RecruiterPerformance"},"type":"array","title":"Recruiter Performance"},"offer_decline_reasons":{"items":{"$ref":"#/components/schemas/OfferDeclineReason"},"type":"array","title":"Offer Decline Reasons"},"application_trend":{"items":{"$ref":"#/components/schemas/ApplicationTrend"},"type":"array","title":"Application Trend"},"cost_per_hire":{"anyOf":[{"$ref":"#/components/schemas/MetricWithDelta"},{"type":"null"}]},"aging_candidates_count":{"type":"integer","title":"Aging Candidates Count","default":0},"stage_durations":{"items":{"$ref":"#/components/schemas/StageDuration"},"type":"array","title":"Stage Durations","default":[]},"pipeline_snapshot":{"items":{"$ref":"#/components/schemas/PipelineSnapshotSlice"},"type":"array","title":"Pipeline Snapshot","default":[]},"funnel_stage_meta":{"anyOf":[{"items":{"$ref":"#/components/schemas/FunnelStageMeta"},"type":"array"},{"type":"null"}],"title":"Funnel Stage Meta"},"per_template_funnels":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateFunnelBreakdown"},"type":"array"},{"type":"null"}],"title":"Per Template Funnels"}},"type":"object","required":["period_start","period_end","previous_period_start","previous_period_end","total_jobs","active_candidates","total_hired","avg_time_to_hire_days","offer_acceptance_rate","candidates_by_stage","conversion_rates","source_effectiveness","top_performing_jobs","recruiter_performance","offer_decline_reasons","application_trend"],"title":"ReportResponse","description":"Full report data returned by GET /api/v1/reports."},"ReportSettingsData":{"properties":{"widget_order":{"items":{"type":"string"},"type":"array","title":"Widget Order","default":["kpi_offer_acceptance","kpi_active_candidates","kpi_total_hired","kpi_time_to_hire","kpi_time_to_fill","job_trend","job_status_by_dept","job_attributes","smart_alerts","application_trend","stage_bar_chart","conversion_funnel","matching_analytics","source_matrix","demographics","top_jobs","rejection_reasons","hired_list"]},"hidden_widgets":{"items":{"type":"string"},"type":"array","title":"Hidden Widgets","default":[]},"chart_preferences":{"additionalProperties":{"type":"string"},"type":"object","title":"Chart Preferences","default":{}},"trend_collapsed":{"type":"boolean","title":"Trend Collapsed","default":false},"color_theme":{"type":"string","title":"Color Theme","default":"classic"}},"type":"object","title":"ReportSettingsData","description":"User-customizable report layout settings."},"ReportSettingsResponse":{"properties":{"settings":{"$ref":"#/components/schemas/ReportSettingsData"}},"type":"object","required":["settings"],"title":"ReportSettingsResponse","description":"Response for GET /reports/settings."},"ResendVerificationRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ResendVerificationRequest","description":"Request a new signup verification email."},"ResetPasswordRequest":{"properties":{"token":{"type":"string","title":"Token"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"}},"type":"object","required":["token","password"],"title":"ResetPasswordRequest","description":"Reset password with a valid token."},"RestoreApplicationRequest":{"properties":{"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"type":"object","title":"RestoreApplicationRequest","description":"Restore a removed/rejected application back to active state."},"ReviewNoteCreate":{"properties":{"content_html":{"type":"string","minLength":1,"title":"Content Html"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"}},"type":"object","required":["content_html"],"title":"ReviewNoteCreate"},"ReviewNoteListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ReviewNoteResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"ReviewNoteListResponse"},"ReviewNoteMutationResponse":{"properties":{"note":{"$ref":"#/components/schemas/ReviewNoteResponse"},"latest_plaintext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Plaintext"}},"type":"object","required":["note","latest_plaintext"],"title":"ReviewNoteMutationResponse","description":"PATCH result — the edited note + the refreshed candidate.notes cache."},"ReviewNotePinRequest":{"properties":{"pinned":{"type":"boolean","title":"Pinned"}},"type":"object","required":["pinned"],"title":"ReviewNotePinRequest"},"ReviewNoteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"application_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Application Id"},"author_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Author User Id"},"author_name":{"type":"string","title":"Author Name"},"content_html":{"type":"string","title":"Content Html"},"content_plaintext":{"type":"string","title":"Content Plaintext"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_deleted":{"type":"boolean","title":"Is Deleted"},"is_pinned":{"type":"boolean","title":"Is Pinned"}},"type":"object","required":["id","candidate_id","application_id","author_user_id","author_name","content_html","content_plaintext","created_at","updated_at","is_deleted","is_pinned"],"title":"ReviewNoteResponse"},"ReviewNoteUpdate":{"properties":{"content_html":{"type":"string","minLength":1,"title":"Content Html"}},"type":"object","required":["content_html"],"title":"ReviewNoteUpdate"},"ReviewerEntry":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"}},"type":"object","required":["email","name"],"title":"ReviewerEntry","description":"A reviewer in a batch HM review request."},"RoleCapabilitiesResponse":{"properties":{"roles":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Roles"}},"type":"object","required":["roles"],"title":"RoleCapabilitiesResponse","description":"Capability sets for the 3 system roles, keyed by backend role string.\n\nRead-only reference that powers the Members page \"role permissions\" table."},"RoleUpdate":{"properties":{"role":{"type":"string","pattern":"^(admin|recruiter|hiring_manager)$","title":"Role"}},"type":"object","required":["role"],"title":"RoleUpdate","description":"Change a tenant member's role (admin-only)."},"ScheduledEmailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"to_email":{"type":"string","title":"To Email"},"subject":{"type":"string","title":"Subject"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"followup_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Followup Of Id"}},"type":"object","required":["id","candidate_id","to_email","subject","scheduled_at","created_at"],"title":"ScheduledEmailResponse","description":"Response for a scheduled email."},"SelfScheduleSlotInput":{"properties":{"start_time":{"type":"string","format":"date-time","title":"Start Time"},"duration_minutes":{"type":"integer","maximum":480.0,"minimum":15.0,"title":"Duration Minutes","default":60}},"type":"object","required":["start_time"],"title":"SelfScheduleSlotInput","description":"A time slot offered for candidate self-scheduling."},"SendTestRequest":{"properties":{"to":{"type":"string","format":"email","title":"To"}},"type":"object","required":["to"],"title":"SendTestRequest"},"SendTestResponse":{"properties":{"sent":{"type":"boolean","title":"Sent"}},"type":"object","required":["sent"],"title":"SendTestResponse"},"SequenceCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"trigger_type":{"type":"string","title":"Trigger Type","default":"manual"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"},"steps":{"items":{"$ref":"#/components/schemas/StepCreate"},"type":"array","title":"Steps"}},"type":"object","required":["name"],"title":"SequenceCreate","description":"Schema for creating a drip sequence with optional initial steps."},"SequenceDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"trigger_type":{"type":"string","title":"Trigger Type"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"},"status":{"type":"string","title":"Status"},"total_enrolled":{"type":"integer","title":"Total Enrolled"},"total_completed":{"type":"integer","title":"Total Completed"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"steps":{"items":{"$ref":"#/components/schemas/StepResponse"},"type":"array","title":"Steps"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"}},"type":"object","required":["id","tenant_id","name","trigger_type","status","total_enrolled","total_completed","created_at","updated_at"],"title":"SequenceDetailResponse","description":"Response with steps included."},"SequenceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"trigger_type":{"type":"string","title":"Trigger Type"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"},"status":{"type":"string","title":"Status"},"total_enrolled":{"type":"integer","title":"Total Enrolled"},"total_completed":{"type":"integer","title":"Total Completed"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","name","trigger_type","status","total_enrolled","total_completed","created_at","updated_at"],"title":"SequenceResponse","description":"Response schema for a drip sequence."},"SequenceUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"trigger_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trigger Type"},"trigger_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trigger Config"}},"type":"object","title":"SequenceUpdate","description":"Schema for updating sequence metadata (draft/paused only)."},"SharedAttachment":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"file_url":{"type":"string","title":"File Url"},"original_filename":{"type":"string","title":"Original Filename"},"file_size_bytes":{"type":"integer","title":"File Size Bytes"},"content_type":{"type":"string","title":"Content Type"},"attachment_type":{"type":"string","title":"Attachment Type"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["id","file_url","original_filename","file_size_bytes","content_type","attachment_type"],"title":"SharedAttachment","description":"Attachment info shared with HM reviewer."},"SharedExpectedSalary":{"properties":{"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"}},"type":"object","title":"SharedExpectedSalary","description":"Candidate's expected salary range shared with HM reviewer."},"SharedHRReview":{"properties":{"star_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Star Rating"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"SharedHRReview","description":"Recruiter's internal review of the candidate — star rating + notes.\n\nNote: `tags` remains in the schema for backward-compat with existing clients\nbut is always returned as `[]`. HM-facing UI never rendered tags."},"SharedLink":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"link_type":{"type":"string","title":"Link Type"},"url":{"type":"string","title":"Url"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","required":["id","link_type","url"],"title":"SharedLink","description":"Link info shared with HM reviewer."},"SharedMatchingScore":{"properties":{"overall_score":{"type":"integer","title":"Overall Score"},"recommendation":{"type":"string","title":"Recommendation"},"hard_skills_score":{"type":"integer","title":"Hard Skills Score"},"experience_relevance_score":{"type":"integer","title":"Experience Relevance Score"},"overall_reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Overall Reasoning"},"strengths":{"items":{"type":"string"},"type":"array","title":"Strengths"},"gaps":{"items":{"type":"string"},"type":"array","title":"Gaps"}},"type":"object","required":["overall_score","recommendation","hard_skills_score","experience_relevance_score"],"title":"SharedMatchingScore","description":"AI matching score shared with HM reviewer (full breakdown + reasoning)."},"SitemapPageEntry":{"properties":{"subdomain":{"type":"string","title":"Subdomain"},"tenant_code":{"type":"string","title":"Tenant Code"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["subdomain","tenant_code","updated_at"],"title":"SitemapPageEntry","description":"Lightweight entry for sitemap generation."},"SourceCareerFormUpdate":{"properties":{"show_on_career_form":{"type":"boolean","title":"Show On Career Form"}},"type":"object","required":["show_on_career_form"],"title":"SourceCareerFormUpdate"},"SourceEffectiveness":{"properties":{"source":{"type":"string","title":"Source"},"group_key":{"type":"string","title":"Group Key"},"label":{"type":"string","title":"Label"},"total_applications":{"type":"integer","title":"Total Applications"},"hired_count":{"type":"integer","title":"Hired Count"},"hire_rate":{"type":"number","title":"Hire Rate"}},"type":"object","required":["source","group_key","label","total_applications","hired_count","hire_rate"],"title":"SourceEffectiveness","description":"Hire attribution by candidate source."},"SourceMatrixCell":{"properties":{"source":{"type":"string","title":"Source"},"group_key":{"type":"string","title":"Group Key"},"source_label":{"type":"string","title":"Source Label"},"stage":{"type":"string","title":"Stage"},"stage_label":{"type":"string","title":"Stage Label"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["source","group_key","source_label","stage","stage_label","count"],"title":"SourceMatrixCell","description":"One cell in the source × stage matrix."},"SourceMatrixResponse":{"properties":{"sources":{"items":{"type":"string"},"type":"array","title":"Sources"},"stages":{"items":{"type":"string"},"type":"array","title":"Stages"},"data":{"items":{"$ref":"#/components/schemas/SourceMatrixCell"},"type":"array","title":"Data"}},"type":"object","required":["sources","stages","data"],"title":"SourceMatrixResponse","description":"Source matrix grouped by source and stage."},"SourceResponse":{"properties":{"value":{"type":"string","title":"Value"},"name":{"type":"string","title":"Name"},"is_custom":{"type":"boolean","title":"Is Custom","default":false},"parent_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Source"},"show_on_career_form":{"type":"boolean","title":"Show On Career Form","default":false}},"type":"object","required":["value","name"],"title":"SourceResponse"},"SourceSelector":{"properties":{"source":{"type":"string","title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"}},"type":"object","required":["source"],"title":"SourceSelector","description":"Identifies one (source, source_detail) pair to include in an operation."},"SourceTarget":{"properties":{"source":{"type":"string","title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"}},"type":"object","required":["source"],"title":"SourceTarget","description":"The destination (source, source_detail) after the operation."},"SourceValueRow":{"properties":{"source":{"type":"string","title":"Source"},"source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Detail"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["source","source_detail","count"],"title":"SourceValueRow","description":"One distinct (source, source_detail) pair with a candidate count."},"SourceValuesResponse":{"properties":{"values":{"items":{"$ref":"#/components/schemas/SourceValueRow"},"type":"array","title":"Values"}},"type":"object","required":["values"],"title":"SourceValuesResponse","description":"Response from GET /source-management/values."},"SourcingAddCandidateRequest":{"properties":{"full_name":{"type":"string","title":"Full Name"},"profile_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Url"},"platform":{"type":"string","enum":["linkedin","github","facebook"],"title":"Platform"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["full_name","platform"],"title":"SourcingAddCandidateRequest","description":"Create a candidate from a search result."},"SourcingBuildQueryRequest":{"properties":{"platform":{"type":"string","enum":["linkedin","github","facebook","resume"],"title":"Platform"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"skills":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"title":"Skills","default":""},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"exclude_keywords":{"items":{"type":"string"},"type":"array","title":"Exclude Keywords"},"open_to_work":{"type":"boolean","title":"Open To Work","default":false},"experience_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience Level"},"education":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},"type":"object","required":["platform"],"title":"SourcingBuildQueryRequest","description":"Input criteria to build a boolean X-ray query."},"SourcingBuildQueryResponse":{"properties":{"query":{"type":"string","title":"Query"},"google_url":{"type":"string","title":"Google Url"},"breakdown":{"anyOf":[{"$ref":"#/components/schemas/QueryBreakdown"},{"type":"null"}]}},"type":"object","required":["query","google_url"],"title":"SourcingBuildQueryResponse","description":"The constructed boolean query + Google Search URL + structured breakdown."},"SourcingBulkImportItem":{"properties":{"url":{"type":"string","title":"Url"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["url"],"title":"SourcingBulkImportItem","description":"A single profile link to import."},"SourcingBulkImportRequest":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SourcingBulkImportItem"},"type":"array","maxItems":50,"minItems":1,"title":"Items"},"platform":{"type":"string","enum":["linkedin","github","facebook"],"title":"Platform"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["items","platform"],"title":"SourcingBulkImportRequest","description":"Batch import multiple profile links at once."},"SourcingBulkImportResponse":{"properties":{"imported":{"type":"integer","title":"Imported"},"skipped":{"type":"integer","title":"Skipped"},"failed":{"type":"integer","title":"Failed"},"results":{"items":{"$ref":"#/components/schemas/SourcingBulkImportResultItem"},"type":"array","title":"Results"}},"type":"object","required":["imported","skipped","failed","results"],"title":"SourcingBulkImportResponse","description":"Response for bulk import."},"SourcingBulkImportResultItem":{"properties":{"url":{"type":"string","title":"Url"},"candidate_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Id"},"already_exists":{"type":"boolean","title":"Already Exists","default":false},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["url"],"title":"SourcingBulkImportResultItem","description":"Result for a single imported profile."},"SourcingLogSearchRequest":{"properties":{"platform":{"type":"string","enum":["linkedin","github","facebook","resume"],"title":"Platform"},"query_text":{"type":"string","title":"Query Text"},"criteria":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Criteria"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"}},"type":"object","required":["platform","query_text"],"title":"SourcingLogSearchRequest","description":"Log a search after the user opens Google."},"StageChangeRequest":{"properties":{"stage":{"anyOf":[{"$ref":"#/components/schemas/ApplicationStage"},{"type":"null"}]},"stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Stage Id"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"confirmed":{"type":"boolean","title":"Confirmed","default":false},"skip_email":{"type":"boolean","title":"Skip Email","default":false}},"type":"object","title":"StageChangeRequest","description":"Schema for changing application pipeline stage.\n\nAccepts either stage_id (new pipeline) or stage (legacy enum).\nIf stage_id is provided, it takes precedence."},"StageCount":{"properties":{"stage":{"type":"string","title":"Stage"},"label":{"type":"string","title":"Label"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["stage","label","count"],"title":"StageCount","description":"Count for a single pipeline stage (for bar chart)."},"StageDuration":{"properties":{"stage":{"type":"string","title":"Stage"},"label":{"type":"string","title":"Label"},"avg_days":{"type":"number","title":"Avg Days"},"sample_count":{"type":"integer","title":"Sample Count"},"prev_avg_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prev Avg Days"},"delta_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Days"}},"type":"object","required":["stage","label","avg_days","sample_count"],"title":"StageDuration","description":"Average dwell time in one funnel stage before the next transition out.\n\n``avg_days`` is the mean over all transitions LEAVING this stage in the\nperiod (event axis on stage_history.changed_at): days from when the\napplication entered the stage to when it left (forward or reject). ``prev_avg_days``\nis the same metric over the immediately-previous period; ``delta_days`` is\n``avg_days - prev_avg_days`` (None when there's no previous-period sample —\nso the FE shows no delta chip rather than a misleading \"down 100%\")."},"StageHistoryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"changed_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Changed By"},"change_type":{"type":"string","title":"Change Type","default":"stage_move"},"from_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Stage"},"to_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Stage"},"from_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"From Stage Id"},"to_stage_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"To Stage Id"},"from_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Stage Name"},"to_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Stage Name"},"from_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Status"},"to_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Status"},"changed_at":{"type":"string","format":"date-time","title":"Changed At"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"note_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Key"},"note_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Note Params"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"changed_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Changed By Name"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Code"}},"type":"object","required":["id","tenant_id","application_id","changed_by","from_stage","to_stage","changed_at","notes","created_at"],"title":"StageHistoryResponse","description":"Response schema for a stage history entry."},"StageMigration":{"properties":{"old_stage_id":{"type":"string","format":"uuid","title":"Old Stage Id"},"new_stage_index":{"type":"integer","minimum":0.0,"title":"New Stage Index"}},"type":"object","required":["old_stage_id","new_stage_index"],"title":"StageMigration","description":"Maps an old stage to a new stage identified by index in the stages array."},"StageMoveValidation":{"properties":{"allowed":{"type":"boolean","title":"Allowed","default":true},"direction":{"type":"string","title":"Direction","default":"forward"},"needs_confirmation":{"type":"boolean","title":"Needs Confirmation","default":false},"confirmation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirmation Type"},"skipped_required":{"items":{"type":"string"},"type":"array","title":"Skipped Required","default":[]},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","title":"StageMoveValidation","description":"Returned by validate-move endpoint to inform frontend about needed confirmations."},"StageOption":{"properties":{"stage":{"type":"string","title":"Stage"},"stage_name":{"type":"string","title":"Stage Name"},"value":{"type":"string","title":"Value"}},"type":"object","required":["stage","stage_name","value"],"title":"StageOption","description":"One entry in the data-derived stage filter options list.\n\n``stage``      — the enum key (e.g. ``\"interview_1\"``); used for ordering.\n``stage_name`` — the tenant-customised label (e.g. ``\"Phỏng vấn vòng 1\"``).\n``value``      — equals ``stage_name``; what the list endpoint filters on."},"StaleCandidate":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"candidate_code":{"type":"string","title":"Candidate Code"},"job_title":{"type":"string","title":"Job Title"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"stage":{"type":"string","title":"Stage"},"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name"},"days_in_stage":{"type":"integer","title":"Days In Stage","default":0},"last_activity_at":{"type":"string","format":"date-time","title":"Last Activity At"}},"type":"object","required":["application_id","candidate_id","candidate_name","candidate_code","job_title","job_id","stage","last_activity_at"],"title":"StaleCandidate"},"StateResponse":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"type":"string","title":"Name"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"state_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Code"}},"type":"object","required":["id","name"],"title":"StateResponse"},"StatusChangeRequest":{"properties":{"status":{"$ref":"#/components/schemas/ApplicantStatus"},"reason_code":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Reason Code"},"reason_detail":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Reason Detail"},"reason":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Reason"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"offer_accepted_at":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Offer Accepted At"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"send_email":{"type":"boolean","title":"Send Email","default":true},"offer_response_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Offer Response Date"},"reopen_job":{"type":"boolean","title":"Reopen Job","default":false}},"type":"object","required":["status"],"title":"StatusChangeRequest","description":"Schema for changing applicant status (reject/hire/reopen)."},"StepCompanyRequest":{"properties":{"company_name":{"type":"string","maxLength":255,"minLength":2,"title":"Company Name"},"logo_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Logo Url"},"industry":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Industry"},"company_size":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Company Size"},"country_code":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Country Code","default":"VN"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"}},"type":"object","required":["company_name"],"title":"StepCompanyRequest","description":"Step 2: company info."},"StepCreate":{"properties":{"delay_days":{"type":"integer","minimum":0.0,"title":"Delay Days"},"subject":{"type":"string","maxLength":500,"title":"Subject"},"body":{"type":"string","title":"Body"}},"type":"object","required":["delay_days","subject","body"],"title":"StepCreate","description":"Schema for creating a drip step."},"StepProfileRequest":{"properties":{"full_name":{"type":"string","maxLength":255,"minLength":2,"title":"Full Name"},"job_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Job Title"},"avatar_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Avatar Url"}},"type":"object","required":["full_name"],"title":"StepProfileRequest","description":"Step 1: user profile data."},"StepRecruitmentRequest":{"properties":{"monthly_candidate_volume":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Monthly Candidate Volume"},"hiring_challenges":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Hiring Challenges"}},"type":"object","title":"StepRecruitmentRequest","description":"Step 3: recruitment goals."},"StepReorderItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"step_order":{"type":"integer","minimum":1.0,"title":"Step Order"}},"type":"object","required":["id","step_order"],"title":"StepReorderItem","description":"Single item in a reorder request."},"StepReorderRequest":{"properties":{"steps":{"items":{"$ref":"#/components/schemas/StepReorderItem"},"type":"array","title":"Steps"}},"type":"object","required":["steps"],"title":"StepReorderRequest","description":"Request to reorder steps."},"StepResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"sequence_id":{"type":"string","format":"uuid","title":"Sequence Id"},"step_order":{"type":"integer","title":"Step Order"},"delay_days":{"type":"integer","title":"Delay Days"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","sequence_id","step_order","delay_days","subject","body","created_at","updated_at"],"title":"StepResponse","description":"Response schema for a drip step."},"StepStatsResponse":{"properties":{"step_order":{"type":"integer","title":"Step Order"},"subject":{"type":"string","title":"Subject"},"delay_days":{"type":"integer","title":"Delay Days"},"sent":{"type":"integer","title":"Sent","default":0},"delivered":{"type":"integer","title":"Delivered","default":0},"opened":{"type":"integer","title":"Opened","default":0},"clicked":{"type":"integer","title":"Clicked","default":0},"bounced":{"type":"integer","title":"Bounced","default":0},"replied":{"type":"integer","title":"Replied","default":0}},"type":"object","required":["step_order","subject","delay_days"],"title":"StepStatsResponse","description":"Per-step analytics."},"StepUpdate":{"properties":{"delay_days":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Delay Days"},"subject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","title":"StepUpdate","description":"Schema for updating a drip step."},"SubdomainListResponse":{"properties":{"subdomains":{"items":{"type":"string"},"type":"array","title":"Subdomains"}},"type":"object","required":["subdomains"],"title":"SubdomainListResponse","description":"Valid career-page subdomains for the Gate 7 edge shield."},"SubdomainUpdate":{"properties":{"subdomain":{"type":"string","maxLength":63,"minLength":3,"title":"Subdomain"}},"type":"object","required":["subdomain"],"title":"SubdomainUpdate","description":"Schema for updating subdomain."},"SubdomainUpdateRequest":{"properties":{"subdomain":{"type":"string","title":"Subdomain"}},"type":"object","required":["subdomain"],"title":"SubdomainUpdateRequest","description":"Request body for setting a page's subdomain."},"SubscribeRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"turnstile_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Turnstile Token"}},"type":"object","required":["email"],"title":"SubscribeRequest","description":"Public newsletter signup payload."},"SubscribeResponse":{"properties":{"status":{"type":"string","title":"Status","default":"pending"},"already":{"type":"boolean","title":"Already","default":false}},"type":"object","title":"SubscribeResponse","description":"Generic signup ack. ``status`` is always ``pending`` for a fresh or\nre-subscribed address; ``already`` is True when the address was already\nconfirmed (so the UI can say \"you're already subscribed\")."},"SubscriberAdminCreate":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"consent_confirmed":{"type":"boolean","title":"Consent Confirmed","default":false}},"type":"object","required":["email"],"title":"SubscriberAdminCreate","description":"Admin adds one address by hand. ``consent_confirmed`` is a required\nattestation (PDPA) — the endpoint rejects False."},"SubscriberAdminUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"email_disabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Email Disabled"}},"type":"object","title":"SubscriberAdminUpdate"},"SubscriberCounts":{"properties":{"pending":{"type":"integer","title":"Pending","default":0},"subscribed":{"type":"integer","title":"Subscribed","default":0},"unsubscribed":{"type":"integer","title":"Unsubscribed","default":0},"disabled":{"type":"integer","title":"Disabled","default":0}},"type":"object","title":"SubscriberCounts"},"SubscriberImportResult":{"properties":{"valid":{"type":"integer","title":"Valid"},"duplicates":{"type":"integer","title":"Duplicates"},"invalid":{"items":{"type":"string"},"type":"array","title":"Invalid"},"created":{"type":"integer","title":"Created"},"dry_run":{"type":"boolean","title":"Dry Run"}},"type":"object","required":["valid","duplicates","invalid","created","dry_run"],"title":"SubscriberImportResult"},"SubscriberListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"source":{"type":"string","title":"Source"},"email_disabled":{"type":"boolean","title":"Email Disabled"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","email","status","source","email_disabled","created_at"],"title":"SubscriberListResponse","description":"Lightweight subscriber list item."},"SubscriberPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SubscriberListResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"counts":{"$ref":"#/components/schemas/SubscriberCounts"}},"type":"object","required":["items","total","counts"],"title":"SubscriberPage"},"SubscriberResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"email":{"type":"string","title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"source":{"type":"string","title":"Source"},"uuid":{"type":"string","format":"uuid","title":"Uuid"},"email_disabled":{"type":"boolean","title":"Email Disabled"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmed At"},"unsubscribed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Unsubscribed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tenant_id","email","status","source","uuid","email_disabled","created_at","updated_at"],"title":"SubscriberResponse","description":"Response schema for a subscriber."},"TalentGroupCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"},"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Candidate Ids"}},"type":"object","required":["name"],"title":"TalentGroupCreate","description":"Create a talent group, optionally with initial members."},"TalentGroupListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"candidate_count":{"type":"integer","title":"Candidate Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"}},"type":"object","required":["id","name","created_at"],"title":"TalentGroupListResponse","description":"Lightweight list item for nav / dropdown."},"TalentGroupMemberAdd":{"properties":{"candidate_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Candidate Ids"}},"type":"object","required":["candidate_ids"],"title":"TalentGroupMemberAdd","description":"Add candidates to a talent group."},"TalentGroupMemberResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"group_id":{"type":"string","format":"uuid","title":"Group Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"candidate_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Name"},"candidate_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Email"},"candidate_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Code"}},"type":"object","required":["id","group_id","candidate_id","created_at"],"title":"TalentGroupMemberResponse","description":"A group member with candidate display info."},"TalentGroupResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"candidate_count":{"type":"integer","title":"Candidate Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"creator_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creator Name"}},"type":"object","required":["id","tenant_id","name","created_at","updated_at"],"title":"TalentGroupResponse","description":"Full talent group response. candidate_count is COMPUTED (operational-filtered)."},"TalentGroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Color"}},"type":"object","title":"TalentGroupUpdate","description":"Update a talent group's name / description / color."},"TalentPoolCandidateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id"},"candidate_code":{"type":"string","title":"Candidate Code"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"},"vn_province_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vn Province Code"},"state_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"State Id"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"current_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Job Title"},"current_company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Company"},"total_experience_years":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Experience Years"},"skills":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Skills"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"source":{"type":"string","title":"Source"},"star_rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Star Rating"},"last_edited_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Last Edited By User Id"},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name"},"is_blacklisted":{"type":"boolean","title":"Is Blacklisted","default":false},"duplicate_of_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Duplicate Of Id"},"needs_manual_review":{"type":"boolean","title":"Needs Manual Review","default":false},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"cv_file_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cv File Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"last_contacted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Contacted At"},"is_active":{"type":"boolean","title":"Is Active","default":false},"application_count":{"type":"integer","title":"Application Count","default":0},"applied_jobs":{"items":{"$ref":"#/components/schemas/AppliedJobInfo"},"type":"array","title":"Applied Jobs","default":[]},"latest_job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Job Title"},"latest_job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Latest Job Id"},"latest_applied_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Latest Applied Date"},"latest_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Stage"},"latest_stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Stage Name"},"last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity At"}},"type":"object","required":["id","tenant_id","candidate_code","full_name","source","created_at","updated_at"],"title":"TalentPoolCandidateResponse","description":"Response for a candidate in the talent pool listing."},"TalentPoolFilterOptions":{"properties":{"locations":{"items":{"type":"string"},"type":"array","title":"Locations","default":[]},"sources":{"items":{"type":"string"},"type":"array","title":"Sources","default":[]},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"skills":{"items":{"type":"string"},"type":"array","title":"Skills","default":[]},"current_job_titles":{"items":{"type":"string"},"type":"array","title":"Current Job Titles","default":[]},"applied_job_titles":{"items":{"type":"string"},"type":"array","title":"Applied Job Titles","default":[]}},"type":"object","title":"TalentPoolFilterOptions","description":"Distinct values for filter dropdowns."},"TalentPoolStats":{"properties":{"total_candidates":{"type":"integer","title":"Total Candidates","default":0},"high_rated_candidates":{"type":"integer","title":"High Rated Candidates","default":0},"new_this_month":{"type":"integer","title":"New This Month","default":0},"with_applications":{"type":"integer","title":"With Applications","default":0},"without_applications":{"type":"integer","title":"Without Applications","default":0}},"type":"object","title":"TalentPoolStats","description":"Summary counts for header cards."},"TemplateAttachment":{"properties":{"filename":{"type":"string","title":"Filename"},"url":{"type":"string","title":"Url"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Type"},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"}},"type":"object","required":["filename","url"],"title":"TemplateAttachment","description":"Attachment metadata stored on an email template."},"TemplateFunnelBreakdown":{"properties":{"template_id":{"type":"string","title":"Template Id"},"template_name":{"type":"string","title":"Template Name"},"candidates_by_stage":{"items":{"$ref":"#/components/schemas/StageCount"},"type":"array","title":"Candidates By Stage"},"conversion_rates":{"items":{"$ref":"#/components/schemas/ConversionRate"},"type":"array","title":"Conversion Rates"}},"type":"object","required":["template_id","template_name","candidates_by_stage","conversion_rates"],"title":"TemplateFunnelBreakdown","description":"One funnel per pipeline template, for the \"All pipelines\" view when the\ncohort spans >=2 templates. Each carries that template's own stage names so\nthe numbers aren't diluted across differently-shaped pipelines (and the user\nsees the real step names they configured, not a collapsed canonical funnel)."},"TenantBriefResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"company_name":{"type":"string","title":"Company Name"},"company_code":{"type":"string","title":"Company Code"},"subdomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subdomain"}},"type":"object","required":["id","company_name","company_code"],"title":"TenantBriefResponse","description":"Brief tenant info included in auth responses."},"TenantInfoResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"company_name":{"type":"string","title":"Company Name"},"company_code":{"type":"string","title":"Company Code"},"subdomain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subdomain"},"logo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Url"}},"type":"object","required":["id","company_name","company_code","subdomain","logo_url"],"title":"TenantInfoResponse","description":"Response for tenant info."},"TenantNameUpdate":{"properties":{"company_name":{"type":"string","maxLength":255,"minLength":1,"title":"Company Name"}},"type":"object","required":["company_name"],"title":"TenantNameUpdate","description":"Schema for renaming the tenant (company display name)."},"TimeToFillMetric":{"properties":{"avg_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Days"},"median_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Median Days"},"job_count":{"type":"integer","title":"Job Count"}},"type":"object","required":["job_count"],"title":"TimeToFillMetric","description":"Time to fill statistics."},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse","description":"JWT token pair response."},"TopJob":{"properties":{"job_id":{"type":"string","title":"Job Id"},"job_code":{"type":"string","title":"Job Code"},"title":{"type":"string","title":"Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"applications_count":{"type":"integer","title":"Applications Count"},"hired_count":{"type":"integer","title":"Hired Count"},"hire_rate":{"type":"number","title":"Hire Rate"},"headcount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Headcount"},"total_cost":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Total Cost"},"cost_per_hire":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cost Per Hire"},"avg_time_to_hire_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Time To Hire Days"}},"type":"object","required":["job_id","job_code","title","department","applications_count","hired_count","hire_rate"],"title":"TopJob","description":"Top performing job by hire rate."},"UndoResponse":{"properties":{"restored_count":{"type":"integer","title":"Restored Count"},"batch_id":{"type":"string","format":"uuid","title":"Batch Id"}},"type":"object","required":["restored_count","batch_id"],"title":"UndoResponse","description":"Response from POST /source-management/undo."},"UnreadCountResponse":{"properties":{"count":{"type":"integer","title":"Count"}},"type":"object","required":["count"],"title":"UnreadCountResponse","description":"Lightweight unread count for badge polling."},"UnsubscribeResponse":{"properties":{"status":{"type":"string","title":"Status"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},"type":"object","required":["status"],"title":"UnsubscribeResponse","description":"Result of an unsubscribe click (idempotent)."},"UpcomingInterview":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_title":{"type":"string","title":"Job Title"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"interview_round":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Interview Round"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"duration_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Minutes"},"meeting_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meeting Link"},"interviewer_names":{"items":{"type":"string"},"type":"array","title":"Interviewer Names","default":[]},"candidate_response_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Response Status"}},"type":"object","required":["id","application_id","candidate_id","candidate_name","job_title","job_id","scheduled_at"],"title":"UpcomingInterview"},"UpcomingOffer":{"properties":{"offer_id":{"type":"string","format":"uuid","title":"Offer Id"},"application_id":{"type":"string","format":"uuid","title":"Application Id"},"candidate_id":{"type":"string","format":"uuid","title":"Candidate Id"},"candidate_name":{"type":"string","title":"Candidate Name"},"job_id":{"type":"string","format":"uuid","title":"Job Id"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"location_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Display"},"status":{"type":"string","title":"Status"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"needs_hire_confirmation":{"type":"boolean","title":"Needs Hire Confirmation","default":false}},"type":"object","required":["offer_id","application_id","candidate_id","candidate_name","job_id","status","sent_at"],"title":"UpcomingOffer"},"UpdateLocaleRequest":{"properties":{"locale":{"type":"string","pattern":"^(vi|en)$","title":"Locale"}},"type":"object","required":["locale"],"title":"UpdateLocaleRequest","description":"Update preferred locale."},"UpdateProfileRequest":{"properties":{"full_name":{"type":"string","maxLength":255,"minLength":1,"title":"Full Name"},"job_title":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Job Title"},"avatar_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Avatar Url"}},"type":"object","required":["full_name"],"title":"UpdateProfileRequest","description":"Self-service update of the current user's profile fields.\n\nReplaces full_name / job_title / avatar_url from the profile page's current\nstate (the frontend sends all three on save). ``avatar_url`` accepts only a\nTick Up preset path or the tenant's own logo — never an arbitrary URL; the\nendpoint enforces that allowlist (the format check is here, the tenant-logo\ncomparison is in the endpoint where the tenant is loaded)."},"UpdateSignatureRequest":{"properties":{"email_signature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Signature"},"auto_append_signature":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Append Signature"}},"type":"object","title":"UpdateSignatureRequest","description":"Update email signature (HTML, optional) + auto-append toggle."},"UsageLimitDetail":{"properties":{"current":{"type":"integer","title":"Current"},"max":{"type":"integer","title":"Max"}},"type":"object","required":["current","max"],"title":"UsageLimitDetail"},"UsageSummaryResponse":{"properties":{"plan":{"type":"string","title":"Plan"},"billing_state":{"type":"string","title":"Billing State","default":"active"},"plan_valid_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Plan Valid Until"},"grace_ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Grace Ends At"},"cycle_started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cycle Started At"},"cycle_resets_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cycle Resets At"},"limits":{"additionalProperties":{"$ref":"#/components/schemas/UsageLimitDetail"},"type":"object","title":"Limits"}},"type":"object","required":["plan","limits"],"title":"UsageSummaryResponse"},"UserListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"full_name":{"type":"string","title":"Full Name"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"is_active":{"type":"boolean","title":"Is Active","default":true},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"}},"type":"object","required":["id","full_name","email","role","avatar_url"],"title":"UserListResponse","description":"Response for a team member in the users list."},"UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"full_name":{"type":"string","title":"Full Name"},"avatar_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Url"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"role":{"type":"string","title":"Role"},"auth_provider":{"type":"string","title":"Auth Provider"},"onboarding_completed":{"type":"boolean","title":"Onboarding Completed","default":true},"is_superadmin":{"type":"boolean","title":"Is Superadmin","default":false},"preferred_locale":{"type":"string","title":"Preferred Locale","default":"vi"},"email_signature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Signature"},"auto_append_signature":{"type":"boolean","title":"Auto Append Signature","default":true},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities","default":[]}},"type":"object","required":["id","email","full_name","role","auth_provider"],"title":"UserResponse","description":"Public user info."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerifyEmailRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"VerifyEmailRequest","description":"Verify a signup email with a verification token."},"VnProvinceResponse":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name En"},"full_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name En"}},"type":"object","required":["code","name"],"title":"VnProvinceResponse"},"app__api__v1__endpoints__calendar__CallbackRequest":{"properties":{"code":{"type":"string","title":"Code"}},"type":"object","required":["code"],"title":"CallbackRequest"},"app__api__v1__endpoints__campaigns__SendTestRequest":{"properties":{"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Email"},"header_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Header Image Url"}},"type":"object","required":["subject","body"],"title":"SendTestRequest","description":"Request body for sending a test email."},"app__schemas__auth__MessageResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"MessageResponse","description":"Generic message response."},"app__schemas__offer_letter__OfferListResponse":{"properties":{"application_id":{"type":"string","format":"uuid","title":"Application Id"},"offers":{"items":{"$ref":"#/components/schemas/OfferLetterResponse"},"type":"array","title":"Offers"}},"type":"object","required":["application_id","offers"],"title":"OfferListResponse","description":"List of all offer versions for an application, newest first."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"},"ApiKey":{"type":"http","description":"Read-only company API key `tk_live_…` (Settings → API & data).","scheme":"bearer"}}}}