import"./chunk-B3pr0VN8.js";import{n as e,t}from"./jsx-runtime-wTfS3W87.js";import{c as n,i as r,n as i,o as a,r as o,s,t as c}from"./docComponents-DMapxRRB.js";e();var l=t(),u=()=>(0,l.jsxs)(l.Fragment,{children:[(0,l.jsxs)(`div`,{className:`docs-page-head`,children:[(0,l.jsx)(`p`,{className:`docs-page-eyebrow`,children:`DEVELOPER GUIDE`}),(0,l.jsx)(`h1`,{className:`docs-page-title`,children:`开发指南`}),(0,l.jsx)(`p`,{className:`docs-page-desc`,children:`面向 ATS、校招系统、招聘外包平台和企业内部 HR 工具，开放简历解析、人岗匹配、批量筛选与 JD 优化四类接口。 企业预充值扣费，Bearer Key 鉴权，请求幂等，全程用量审计。`})]}),(0,l.jsx)(n,{id:`overview`,children:`概览`}),(0,l.jsxs)(s,{children:[(0,l.jsx)(`p`,{children:`当前共 5 个端点，覆盖招聘链路的关键 AI 节点：`}),(0,l.jsxs)(`ul`,{children:[(0,l.jsxs)(`li`,{children:[(0,l.jsx)(`code`,{children:`POST /api/open/v1/resumes/parse`}),` — 简历解析为结构化文本，按页计费`]}),(0,l.jsxs)(`li`,{children:[(0,l.jsx)(`code`,{children:`POST /api/open/v1/matches/resume-jd`}),` — JD 与简历匹配评分，按次计费`]}),(0,l.jsxs)(`li`,{children:[(0,l.jsx)(`code`,{children:`POST /api/open/v1/jds/optimize`}),` — JD 优化，按模型 token 计费`]}),(0,l.jsxs)(`li`,{children:[(0,l.jsx)(`code`,{children:`POST /api/open/v1/batches/screen`}),` — 批量筛选（异步），按候选人数量计费`]}),(0,l.jsxs)(`li`,{children:[(0,l.jsx)(`code`,{children:`GET /api/open/v1/batches/:id`}),` — 查询批量任务进度与排序结果`]})]}),(0,l.jsxs)(`p`,{children:[`基础地址 `,(0,l.jsx)(`code`,{children:`https://api2.bysjob.com`}),`；1 元 = 1 积分，100 point_cents = 1 积分。`]})]}),(0,l.jsx)(r,{cols:2,children:(0,l.jsx)(i,{title:`API 参考`,description:`全部端点的方法、参数、请求响应示例`,to:`/docs/api-reference`,cta:`查看 →`})}),(0,l.jsx)(c,{kind:`note`,title:`首期不开放自助开通`,children:`企业需先绑定招聘者账号与企业资料，由后台发放 API Client 与 API Key。`}),(0,l.jsx)(n,{id:`quickstart`,children:`快速开始`}),(0,l.jsx)(s,{children:(0,l.jsxs)(`p`,{children:[`企业开通后，后台创建 API Client 并发放 `,(0,l.jsx)(`code`,{children:`hecn_live_`}),` 开头的 API Key。明文只在创建时展示一次，服务端只存 SHA-256 哈希。`]})}),(0,l.jsx)(o,{title:`curl · 第一次请求`,code:`curl -X POST https://api2.bysjob.com/api/open/v1/matches/resume-jd \\
  -H "Authorization: Bearer hecn_live_xxx" \\
  -H "Idempotency-Key: quickstart-001" \\
  -H "Content-Type: application/json" \\
  -d '{
    "resume_text": "张三，5 年前端，精通 React/TypeScript",
    "jd_text": "招聘高级前端工程师，要求 React、TypeScript、性能优化"
  }'`}),(0,l.jsx)(c,{kind:`warning`,title:`Key 丢失只能重新发放`,children:`明文 Key 不会再次显示。遗失请到后台吊销旧 Key 并创建新 Key，旧 Key 立即失效。`}),(0,l.jsx)(n,{id:`authentication`,children:`鉴权`}),(0,l.jsx)(s,{children:(0,l.jsxs)(`p`,{children:[`每个请求在 `,(0,l.jsx)(`code`,{children:`Authorization`}),` 头携带 `,(0,l.jsx)(`code`,{children:`Bearer`}),` 前缀的 API Key，与网站登录态完全分离：`]})}),(0,l.jsx)(o,{language:`http`,code:`Authorization: Bearer hecn_live_xxxxxxxxxxxxxxxxxxxx`}),(0,l.jsx)(a,{rows:[{name:`Authorization`,type:`string`,required:!0,description:`Bearer hecn_live_… 形式的 API Key。缺失或无效返回 401 unauthorized。`},{name:`Idempotency-Key`,type:`string`,required:!1,description:`幂等键，最长 160 字符。同一 client + 同一 key 不会重复执行。`},{name:`Content-Type`,type:`string`,required:!1,description:`POST 请求体建议用 application/json。`}]}),(0,l.jsx)(c,{kind:`warning`,title:`Key 安全`,children:`不要把 Key 写进前端代码或公开仓库。建议放服务端环境变量或密钥管理服务。发现泄漏立即吊销。`}),(0,l.jsx)(n,{id:`billing`,children:`计费`}),(0,l.jsx)(s,{children:(0,l.jsxs)(`p`,{children:[`扣费走招聘者角色钱包余额 + 资源包，余额不足返回 `,(0,l.jsx)(`code`,{children:`402 insufficient_points`}),`。响应里的 `,(0,l.jsx)(`code`,{children:`billing`}),` 对象同时给出 point_cents（精确子单位）与 points（展示积分）。`]})}),(0,l.jsx)(a,{rows:[{name:`简历解析 resumes/parse`,type:`按页`,required:!1,description:`TextIn xParse 0.05 积分/页（5 point_cents/页），不向上取整`},{name:`人岗匹配 matches/resume-jd`,type:`按次`,required:!1,description:`固定 1 积分/次（100 point_cents），与模型消耗无关`},{name:`批量筛选 batches/screen`,type:`按候选人`,required:!1,description:`1 积分/位候选人，失败项不扣费，异步结算`},{name:`JD 优化 jds/optimize`,type:`按 token`,required:!1,description:`按模型实际消耗，最低 1 积分/次`},{name:`查询批量任务 batches/:id`,type:`免费`,required:!1,description:`GET 接口不扣费`}]}),(0,l.jsxs)(c,{kind:`warning`,title:`批量任务计费时机`,children:[`批量筛选首响应 `,(0,l.jsx)(`code`,{children:`billed_point_cents`}),` 为 0，真实费用按候选人异步结算，以 GET 查询接口返回为准。首响应额外给出 `,(0,l.jsx)(`code`,{children:`estimated_point_cents`}),` 预估。`]}),(0,l.jsx)(n,{id:`rate-limits`,children:`限流与配额`}),(0,l.jsx)(a,{rows:[{name:`daily_request_limit`,type:`integer`,required:!1,description:`每个 client 每日请求上限，默认 1000。`},{name:`monthly_request_limit`,type:`integer`,required:!1,description:`每个 client 每月请求上限，默认 30000。`}]}),(0,l.jsxs)(s,{children:[(0,l.jsxs)(`p`,{children:[`配额按 client 统计，只计 `,(0,l.jsx)(`code`,{children:`started`}),` 与 `,(0,l.jsx)(`code`,{children:`succeeded`}),` 状态请求，`,(0,l.jsx)(`code`,{children:`failed`}),` 不占配额。两者都为 0 时不限流。超限返回 `,(0,l.jsx)(`code`,{children:`429 open_api_quota_exceeded`}),`，次日/次月自动恢复，或联系商务调高。`]}),(0,l.jsxs)(`p`,{children:[`请求体限制：全局 75MB；简历解析 `,(0,l.jsx)(`code`,{children:`fileDataUrl`}),` 单字段上限 25,000,000 字符（超限 413）；简历文本 ≤12,000 字符，JD 文本 ≤8,000 字符；批量筛选单次 ≤20 份简历。`]})]}),(0,l.jsx)(n,{id:`idempotency`,children:`幂等性`}),(0,l.jsxs)(s,{children:[(0,l.jsxs)(`p`,{children:[`请求头加 `,(0,l.jsx)(`code`,{children:`Idempotency-Key`}),`（最长 160 字符）。同一 client + 同一 key：`]}),(0,l.jsxs)(`ul`,{children:[(0,l.jsx)(`li`,{children:`首次成功 → 后续同 key 直接回放原响应`}),(0,l.jsxs)(`li`,{children:[`正在执行 → 返回 `,(0,l.jsx)(`code`,{children:`409 idempotency_key_in_progress`}),`，稍后重试`]}),(0,l.jsxs)(`li`,{children:[`上次失败 → 返回 `,(0,l.jsx)(`code`,{children:`409 idempotency_key_failed_use_new_key`}),`，换新 key 重试`]})]})]}),(0,l.jsxs)(c,{kind:`note`,title:`崩溃可重试`,children:[`若请求因进程崩溃卡在 `,(0,l.jsx)(`code`,{children:`started`}),` 超 10 分钟，系统自动回收该记录，允许用同一 key 重新执行。失败请求不扣费，回收不会重复扣费。`]}),(0,l.jsx)(n,{id:`errors`,children:`错误处理`}),(0,l.jsx)(s,{children:(0,l.jsxs)(`p`,{children:[`错误响应统一结构 `,(0,l.jsx)(`code`,{children:`{ "ok": false, "error": "...", "message": "..." }`}),`。402 额外返回 `,(0,l.jsx)(`code`,{children:`required_point_cents`}),` / `,(0,l.jsx)(`code`,{children:`balance_point_cents`}),` / `,(0,l.jsx)(`code`,{children:`resource_point_cents`}),`。`]})}),(0,l.jsx)(`div`,{className:`doc-table-wrap`,children:(0,l.jsxs)(`table`,{className:`doc-table`,children:[(0,l.jsx)(`thead`,{children:(0,l.jsxs)(`tr`,{children:[(0,l.jsx)(`th`,{children:`状态`}),(0,l.jsx)(`th`,{children:`错误码`}),(0,l.jsx)(`th`,{children:`说明`})]})}),(0,l.jsx)(`tbody`,{children:[[`400`,`invalid_input`,`请求参数校验失败，detail 返回具体字段问题`],[`401`,`unauthorized`,`缺少或无效的 Bearer API Key`],[`402`,`insufficient_points`,`钱包余额不足，返回所需与可用 point_cents`],[`403`,`recruiter_role_required`,`API Key 绑定账号不是招聘者角色`],[`404`,`not_found`,`批量任务不存在或不属于该 client`],[`409`,`idempotency_key_in_progress`,`同一幂等键正在执行中，请稍后重试`],[`409`,`idempotency_key_failed_use_new_key`,`该幂等键对应请求已失败，请用新键重试`],[`413`,`payload_too_large`,`请求体或 data URL 超出上限`],[`429`,`open_api_quota_exceeded`,`超出每 client 日 / 月请求配额`],[`500`,`open_api_error`,`服务端内部错误，可重试；失败不扣费`]].map(([e,t,n])=>(0,l.jsxs)(`tr`,{children:[(0,l.jsx)(`td`,{children:e}),(0,l.jsx)(`td`,{children:(0,l.jsx)(`code`,{children:t})}),(0,l.jsx)(`td`,{children:n})]},`${e}-${t}`))})]})}),(0,l.jsx)(s,{children:(0,l.jsx)(`p`,{children:`重试策略：5xx 与网络超时可重试（失败不扣费）；429 等配额恢复；409 in_progress 等几秒同 key 重试；409 failed 换新 key；402 充值后重试。`})})]});export{u as DocsGuidePage};