EchoScan API 与接入指南

EchoScan 面向敏感访问和业务动作提供设备身份与访问风险结果。Browser Verifier 提交检测并返回服务端签发的 imprint;服务端使用 secret API key 查询 Report API v1。

推荐接入流程

  1. 创建 Browser Environment,并配置精确 Allowed Origins。
  2. 把公开 environmentId 复制进 Browser Verifier,得到 { imprint }
  3. imprint 随受保护业务动作发送到你的服务端。
  4. 独立创建服务端 Secret API Key,不把它与 Environment 当成一个对象。
  5. Secret 只保存到后端,并按 Imprint 查询统一 Report Endpoint。
  6. 读取 risk.status,Pro 还可读取 risk.reasons;只向浏览器返回客户自己的最小业务决策。

浏览器代码和服务端 route 可以位于同一仓库。安全边界取决于运行位置:environmentId 可以公开,API key 只能存在于服务端。

浏览器生成 imprint

Direct 模式必须配置固定格式 env_<32 lowercase hex>environmentId。Browser Verifier 只在指纹 Submit 时使用它,不接受 Workspace ID,也不会把 API key 或 Authorization 放进浏览器。

安装命令
npm install @echoscan/browser-verifier
JavaScript
import { createEchoScan } from '@echoscan/browser-verifier'

const sdk = createEchoScan({
  environmentId: 'env_0123456789abcdef0123456789abcdef'
})
const { imprint } = await sdk.run()
HTML
<script type="module">
  import { createEchoScan } from 'https://cdn.echoscan.org/v1/echoscan.esm.js'

  const sdk = createEchoScan({
    environmentId: 'env_0123456789abcdef0123456789abcdef'
  })
  const { imprint } = await sdk.run()
</script>

<script src="https://cdn.echoscan.org/v1/echoscan.umd.js"></script>
<script>
  const sdk = window.EchoScan.createEchoScan({
    environmentId: 'env_0123456789abcdef0123456789abcdef'
  })
  sdk.run().then(({ imprint }) => {
    console.log(imprint)
  })
</script>

run() 只返回 { imprint }。新 Imprint 格式为 imp_<32 lowercase hex>

Allowed Origins 是浏览器部署保护和错误配置防护,不是秘密认证。只登记完整的 http / https Origin,例如 https://staging.example.com:8443http://localhost:3000;匹配保留 Scheme 和 Port,并统一小写 Host。Path、Query、Fragment、UserInfo、通配符(包括 *.example.com)、裸域名、nullfile:// 和扩展 Origin 全部拒绝。空 Allowlist 或缺少 Origin Header 会拒绝所有 Public Submit。

发送到服务端

按你的业务 API 结构,把 Imprint 随受保护动作发送到服务端。

请求示例
await fetch('/api/your-action', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    ...yourActionPayload,
    echoscanImprint: imprint
  })
})
请求示例
await fetch('/api/your-action', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-EchoScan-Imprint': imprint
  },
  body: JSON.stringify(yourActionPayload)
})
请求示例
await fetch('/api/echoscan/report', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ imprint })
})

上面的 /api/echoscan/report 是接入方自建的示例路径,不是 EchoScan Endpoint。

Lite 接入

Lite 使用统一 Report Endpoint。Secret key 只能由服务端代码读取。

查询 report

请求示例
GET https://api.echoscan.org/api/v1/fingerprint/report/{imprint}
X-API-Key: <your_lite_key>
Accept: application/json

Node.js、Go、Python 和 Rust SDK 封装同一套服务端 HTTP API。

后端语言
SDK 安装 / 依赖
npm install @echoscan/echoscan
服务端查询示例
import { createLiteClient } from '@echoscan/echoscan'

const echoscan = createLiteClient({
  apiKey: process.env.ECHOSCAN_LITE_KEY
})

const report = await echoscan.getReport(imprint)
console.log(report.risk.status)

Lite report

Lite 返回最小公开设备身份与风险契约,不包含产品 Reasons、近期 Activity、设备时间和 Pro 网络详情。

正常访问示例:

返回示例
{
  "schema_version": "1.0",
  "imprint": "imp_0123456789abcdef0123456789abcdef",
  "created_at": "2026-07-28T01:30:00Z",
  "device": {
    "id": "did_A12B34C56D78",
    "seen_before": true,
    "access_count": 8
  },
  "risk": {
    "status": "PASS"
  },
  "browser": {
    "status": "PASS",
    "name": "Google Chrome",
    "version": "145"
  },
  "operating_system": {
    "status": "PASS",
    "name": "Windows",
    "version": "11"
  },
  "network": {
    "status": "PASS",
    "observed_ip": "203.0.113.10",
    "country_code": "JP"
  }
}

可疑访问示例:

返回示例
{
  "schema_version": "1.0",
  "imprint": "imp_11111111111111111111111111111111",
  "created_at": "2026-07-28T01:35:00Z",
  "device": {
    "id": "did_C98D76E54F32",
    "seen_before": false,
    "access_count": 1
  },
  "risk": {
    "status": "SUSPICIOUS"
  },
  "browser": {
    "status": "SUSPICIOUS",
    "name": "Google Chrome",
    "version": "145"
  },
  "operating_system": {
    "status": "PASS",
    "name": "Windows",
    "version": "11"
  },
  "network": {
    "status": "PASS",
    "observed_ip": "198.51.100.20",
    "country_code": "US"
  }
}

复访设备示例:

返回示例
{
  "schema_version": "1.0",
  "imprint": "imp_22222222222222222222222222222222",
  "created_at": "2026-07-28T02:00:00Z",
  "device": {
    "id": "did_A12B34C56D78",
    "seen_before": true,
    "access_count": 8
  },
  "risk": {
    "status": "PASS"
  },
  "browser": {
    "status": "PASS",
    "name": "Google Chrome",
    "version": "145"
  },
  "operating_system": {
    "status": "PASS",
    "name": "Windows",
    "version": "11"
  },
  "network": {
    "status": "PASS",
    "observed_ip": "203.0.113.10",
    "country_code": "JP"
  }
}

字段说明

字段 含义
schema_version 公开报告契约版本
imprint 本次检测的服务端正式报告编号
created_at 报告创建完成时间
device.id 已认证 Workspace 内的设备 ID
device.seen_before 本次之前是否见过该设备
device.access_count 包含本次在内的设备访问次数
risk.status 本次访问的总体商业风险状态
browser 最终浏览器状态、名称和版本
operating_system 最终操作系统状态、名称和版本
network.status 参与总体 Risk 的网络状态
network.observed_ip 服务端观察到的请求出口 IP
network.country_code Observed IP 对应国家或地区代码

状态说明

status 含义
PASS 所有商业 Finding 均为 PASS
SUSPICIOUS 至少一个 Finding 为 SUSPICIOUS,且没有 DECEPTIVE
DECEPTIVE 至少一个 Finding 为 DECEPTIVE

真实关键数据缺失时,总体结果不会是 PASS

Pro 接入

Pro 与 Lite 使用相同的浏览器 Imprint、服务端 Secret 边界和统一 Endpoint。客户升级套餐无需更换 Endpoint;Enterprise 当前返回 Pro 契约。

查询 report

请求示例
GET https://api.echoscan.org/api/v1/fingerprint/report/{imprint}
X-API-Key: <your_pro_key>
Accept: application/json

History 只允许 Pro 和 Enterprise:

请求示例
GET https://api.echoscan.org/api/v1/fingerprint/imprint/{imprint}/history?days=7&recent=20
X-API-Key: <your_pro_key>
Accept: application/json
请求示例
GET https://api.echoscan.org/api/v1/fingerprint/imprint/{imprint}/history?from=2026-03-01&to=2026-03-18&recent=20
X-API-Key: <your_pro_key>
Accept: application/json
后端语言
SDK 安装 / 依赖
npm install @echoscan/echoscan
服务端查询示例
import { createProClient } from '@echoscan/echoscan'

const echoscan = createProClient({
  apiKey: process.env.ECHOSCAN_PRO_KEY
})

const report = await echoscan.getReport(imprint)
console.log(report.risk.status, report.risk.reasons)
const history = await echoscan.getHistory(imprint, { days: 7 })

Pro report

Pro 是 Lite 的严格超集,增加设备连续性时间、产品级 Reasons、可选网络详情和近期 Activity。

返回示例
{
  "schema_version": "1.0",
  "imprint": "imp_0123456789abcdef0123456789abcdef",
  "created_at": "2026-07-28T01:30:00Z",
  "device": {
    "id": "did_A12B34C56D78",
    "seen_before": true,
    "access_count": 42,
    "first_seen_at": "2026-06-10T03:20:00Z",
    "previous_seen_at": "2026-07-27T08:40:00Z"
  },
  "risk": {
    "status": "DECEPTIVE",
    "reasons": [
      "BROWSER_VERSION_MISMATCH",
      "PROXY_DETECTED",
      "NETWORK_INCONSISTENT"
    ]
  },
  "browser": {
    "status": "DECEPTIVE",
    "name": "Google Chrome",
    "version": "145"
  },
  "operating_system": {
    "status": "PASS",
    "name": "Windows",
    "version": "11"
  },
  "network": {
    "status": "DECEPTIVE",
    "observed_ip": "198.23.233.104",
    "country_code": "US",
    "alternate_ip": "126.234.173.23",
    "ip_consistency": "MISMATCH",
    "proxy_detected": true,
    "provider": "Example Hosting Provider",
    "connection_type": "proxy",
    "asn": 36352
  },
  "activity": {
    "5m": {
      "events": 2,
      "distinct_ips": 1,
      "distinct_countries": 1
    },
    "1h": {
      "events": 8,
      "distinct_ips": 2,
      "distinct_countries": 2
    },
    "24h": {
      "events": 21,
      "distinct_ips": 4,
      "distinct_countries": 3
    }
  }
}

Pro 的 PASS Report 仍会明确序列化空 Reasons 数组:

返回示例
{
  "risk": {
    "status": "PASS",
    "reasons": []
  }
}

无法可靠获得的可选字段会省略。首次访问时 device.previous_seen_atnull。只有识别到另一公网 IP 时才返回 network.alternate_ipnetwork.ip_consistency 取值为 MATCHMISMATCHUNKNOWNnetwork.connection_type 取值为 residentialmobilecorporatehostingproxyunknown

产品级风险原因

Reason 含义
BROWSER_VERSION_MISMATCH 浏览器版本信息存在不一致
BROWSER_IDENTITY_MISMATCH 浏览器整体身份信息存在不一致
OS_ENVIRONMENT_MISMATCH 操作系统环境信息存在不一致
AUTOMATION_DETECTED 检测到自动化访问
ENVIRONMENT_INCONSISTENT 当前设备或浏览器环境信息整体不一致
PROXY_DETECTED 检测到代理或 VPN 风险
HOSTING_NETWORK_DETECTED 当前访问来自托管服务或数据中心网络
NETWORK_INCONSISTENT 当前访问的网络身份信息存在不一致
LOCATION_INCONSISTENT 当前访问的位置相关信息存在不一致
SIGNAL_DATA_INCOMPLETE 本次检测缺少形成完整结果所需的关键数据

Reason 表达风险类别,不表达严重程度;严重程度只由 risk.status 表达。

Pro 增量字段

字段 含义
device.first_seen_at 当前 Workspace 首次见到设备的时间
device.previous_seen_at 本次报告之前最近一次访问时间
risk.reasons 稳定、去重的产品级风险类别
network.alternate_ip EchoScan 识别到的另一公网 IP
network.ip_consistency 公网 IP 一致性结果
network.proxy_detected 代理或 VPN 风险标识
network.location 可选国家、地区、城市和时区
network.provider 与 observed_ip 对应的可选 Provider
network.connection_type 稳定连接类型机器值
network.asn 与 observed_ip 对应的可选 ASN
activity.5mactivity.1hactivity.24h 包含本次访问的事件数、不同 IP 数和不同国家数

Pro history

History API 只允许 Pro 和 Enterprise。

返回示例
{
  "imprint": "imp_33333333333333333333333333333333",
  "range": {
    "from": "2026-03-01",
    "to": "2026-03-18",
    "days": 18
  },
  "summary": {
    "events": 12,
    "truncated": false,
    "firstSeenAt": "2026-03-01T08:10:00+09:00",
    "lastSeenAt": "2026-03-18T21:34:00+09:00"
  },
  "timeline": [
    {
      "date": "2026-03-01",
      "count": 2
    },
    {
      "date": "2026-03-18",
      "count": 3
    }
  ],
  "recent": [
    {
      "at": "2026-03-18T21:34:00+09:00",
      "surface": "login"
    }
  ]
}

daysfrom/to 互斥;fromto 必须一起提供,格式固定为 YYYY-MM-DD

服务端决策

使用 risk.status 作为主要报告输入,并结合账号、交易和业务上下文。Pro 还可以使用 risk.reasons、网络详情、Activity 和 History。

JavaScript
const decision =
  report.risk.status === 'PASS'
    ? 'allow'
    : 'challenge'

return Response.json({ decision })

这个 allow / challenge 分支只是客户自己的示例策略;EchoScan Report API v1 不返回 recommended_action

完整 Report 应留在服务端,只向浏览器返回业务所需的最小结果。

错误结构

返回示例
{
  "error": {
    "code": "auth_failed",
    "message": "Authentication failed"
  }
}

建议业务逻辑优先基于 error.code 判断,error.message 仅用于展示。

AI 编码工具接入

让编码 Agent 修改接入前先读取:

  • https://echoscan.org/llms.txt
  • https://echoscan.org/docs/ai-context.md

这些文件与本页面来自同一份 Report API v1 事实源。