跳至正文

Fileverity API 文档

受理流程中的文档检测

在受理流程中加入文档检测:上传、接收 Webhook、按风险等级分流、排入人工复核队列、保存报告编号并在之后核验。

查看 Markdown更新于 2026-11-04

本示例把文档检测置于接收外部文档的流程之前,例如贷款申请、保险理赔、供应商入驻或费用报销。每份文档只检测一次,按风险等级分流,其报告编号作为审计记录保存。API 返回风险等级和处置建议,最终由您的策略和复核人员作出决定。

它使用模型 fvdoc-3,并使用文件、分析和 Webhooks 中的调用。使用测试密钥时,上传和检测会立即返回示例结果,但不会发送 Webhook,也没有示例 PDF。如需试用您的接收程序,请在控制台中对 Webhook 端点使用发送测试。

流程

  1. 用 POST /files 上传文件,用 POST /analyses 发起检测。将您的案件 ID 放入 metadata,并发送 Idempotency-Key。
  2. 立即响应您的用户。文档可能需要排队,因此不要让其请求一直挂起;检测完成时由 Webhook 通知您。
  3. 接收 analysis.completed 或 analysis.failed,校验签名,并将任务加入队列。
  4. 在任务中获取该分析,按其摘要分流,并将结果和 PDF 报告与案件一并保存。
  5. 将需要人工处理的案件送入复核队列,并附上 PDF。
  6. 之后,用保存的文件核验该报告。

1. 上传并发起检测

最大 4 MB 的文件以 multipart 方式上传。更大的文件(最大 50 MB)请按文件中的说明使用预签名上传。创建分析会返回 202 和 status: processing(使用测试密钥时返回 200 和已完成的示例结果),您的 metadata 会随分析一同返回,并出现在该分析的每个 Webhook 中。

FILE_ID=$(curl -s https://api.fileverity.com/v1/files \  -H "Authorization: Bearer $FILEVERITY_API_KEY" \  -H "Idempotency-Key: intake-A-10492-file" \  -F file=@application.pdf | jq -r .id) curl https://api.fileverity.com/v1/analyses \  -H "Authorization: Bearer $FILEVERITY_API_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: intake-A-10492-check" \  -d "{\"model\": \"fvdoc-3\", \"file\": \"$FILE_ID\", \"metadata\": {\"case_id\": \"A-10492\"}}"
{  "id": "an_8Hk2pQ4vN9sL1xR7cW3mY6zB",  "object": "analysis",  "created": 1793700120,  "model": "fvdoc-3-2026-11-03",  "livemode": true,  "status": "processing",  "file": {    "name": "application.pdf",    "bytes": 18874368,    "format": "pdf"  },  "report_id": null,  "report_url": null,  "summary": null,  "result": null,  "error": null,  "progress": {    "stage": "queued",    "done": 0,    "total": 0,    "position": 1  },  "usage": {    "amount": 599,    "currency": "usd",    "funding": "balance"  },  "metadata": {    "case_id": "A-10492"  },  "completed_at": null,  "expires_at": null}

请将 id 与案件一并保存。由于 Idempotency-Key 由案件 ID 派生,超时后再次运行 submit 会返回第一次的响应,而不会重复上传文件,也不会重复计费。Idempotency-Key 保留 24 小时;参见幂等性。

2. 接收结果

使用 Webhooks 中的 verify 函数校验签名,并将其保存为 verify.js 或 verify.py。请快速返回 2xx,并在任务中完成实际工作。enqueue 代表您自己的任务队列。请以事件 ID 为键存储每个任务,这样重复投递就不会创建第二个任务。

import express from "express";import { verify } from "./verify.js"; const app = express(); app.post("/webhooks/fileverity", express.raw({ type: "application/json" }), async (req, res) => {  let event;  try {    event = verify(process.env.FILEVERITY_WEBHOOK_SECRET, req.headers, req.body.toString("utf8"));  } catch {    return res.sendStatus(400);  }  if (event.type === "analysis.completed" || event.type === "analysis.failed") {    await enqueue({ eventId: event.id, analysisId: event.data.id });  }  res.sendStatus(200);});

3. 按风险等级分流

summary 是文档检测稳定且机器可读的判定结果。level 的取值从 L1 到 L5,action 是建议的下一步。请同时依据两者分流,并将任何无法识别的值交给人工处理。

摘要含义分流示例
L1 或 L2,accept未发现篡改迹象。L1 表示来源已验证。自动继续处理。保存报告编号。
L1 或 L2,note没有篡改迹象,但报告中标出了 AI 撰写的文本或 AI 标识。继续处理;如果您的策略限制 AI 撰写的内容,请标记该案件。
L3, review需要人工复核。常规复核队列。
L4, review高风险。优先复核队列。
L5, reject报告中已确认存在问题。优先复核队列。拒绝任何案件之前,须由人工确认。
status 为 failed 或 canceled检测未完成,未扣费。重新上传已保存的原始文件,或将案件交给人工处理。

这种对应关系体现的是您自己的策略。修改该函数,即可把 L3 放入优先队列,或让 note 进入复核。action 的取值集合还包括 resubmit,函数将其视为索取文件另一份副本的请求。摘要中的每个字段都在分析中有说明。

export function route(analysis) {  if (analysis.status !== "succeeded") return "manual";  const { action, level } = analysis.summary;  if (action === "accept") return "accept";  if (action === "note") return "accept_with_note";  if (action === "resubmit") return "request_new_copy";  if (action === "reject" || level === "L4" || level === "L5") return "priority_review";  return "review";}

4. 保存报告编号和 PDF

该任务获取分析、对其分流,并保存之后需要用到的内容。它复用前面步骤中的 call、route 和凭据,saveCase 和 saveReport 代表您自己的存储。请在同一个任务中下载 PDF:分析结果保留 7 天,文档的页面图片和文本摘录保留 3 小时,此后 Fileverity 只保留核验记录,不保留完整报告。

export async function handleResult(analysisId) {  const analysis = await call(`/analyses/${analysisId}`, { headers: auth });  const decision = route(analysis);  await saveCase(analysis.metadata.case_id, {    analysisId: analysis.id,    reportId: analysis.report_id,    reportUrl: analysis.report_url,    summary: analysis.summary,    model: analysis.model,    decision,  });  if (analysis.status === "succeeded") {    const pdf = await fetch(`${base}/analyses/${analysis.id}/report.pdf`, { headers: auth });    await saveReport(analysis.report_id, Buffer.from(await pdf.arrayBuffer()));  }  return decision;}
  • report_id(FV-XXXX-XXXX-XXXX)是查找审计记录的依据。请将其与案件一并保存,存入您的数据库,并写在所有决定通知书上。
  • model 是产生该结果的带日期快照,因此您之后可以准确说明是哪个版本检测了该文档。
  • 请把原始文件保存在您自己的存储中。分析开始时,Fileverity 会删除已上传的文件,检测失败后需要重新上传。参见数据保留与安全。

5. 运行人工复核队列

为每个已分流的案件创建一个任务。向复核人员提供无需再次调用 API 即可作出决定所需的内容:

  • 案件 ID、level、action、reason 以及 findings 中的发现 ID,并附上 PDF 报告。PDF 会列出每项发现及其位置和证据。
  • 您保存的原始文件。
  • report_url,即公开核验页。它确认报告记录和文件指纹,但不能代替阅读报告本身。

在您自己的系统中,将复核人员、决定和时间记录在 report_id 旁边。

检测未发现问题,并不能证明文档是真实的;检测发现了问题,也不能证明存在欺诈。请勿仅凭 API 结果拒绝案件。对于收入、身份或所有权类文档,请通过您自行查得的联系方式向出具方核实。文档伪造检测指南介绍了按文档类型应检查哪些内容。

6. 稍后核验报告

数月之后,审计人员或客户无需 Fileverity 账号即可核对该记录。打开保存的 report_url,页面会显示报告类型、记录的发现和下一步操作、被检测文件的 SHA-256 指纹,以及 RFC 3161 时间戳。把您保存的原始文件拖到页面上,浏览器会计算其 SHA-256 并与记录比对,不会上传任何内容。任何重新保存、转换或编辑过的副本都会得出不同的指纹。

您也可以在自己的系统中执行同样的比对:

sha256sum application.pdf

核验不会再次分析文件,也不证明文档是真实的。它只记录检测了哪份文件、报告给出的结论是什么,以及检测的时间。完整报告只存在于您保存的 PDF 中。报告的各字段在报告对象中有说明。

上线之前

  • 请先使用测试密钥开发。它会立即返回示例结果:风险等级 L2,处置建议 accept,不会运行模型。Webhook 和 PDF 下载需要 Live 密钥,您可以用免费额度来试用。请把分析中的其他摘要传入 route,以测试每个分支。
  • 处理 503 service_unavailable:等待 retry-after 秒后,使用相同的 Idempotency-Key 重试。参见服务繁忙时。
  • 为密钥设置每月支出上限,并添加 balance.low Webhook,以免受理因 insufficient_balance 而中断。参见价格与计费。
  • 请从您的服务器调用 API,并将密钥保存在密钥管理服务中,切勿放在浏览器代码里。
  • 联系技术支持时,请提供 x-request-id 响应头的值。