跳到正文
开灵科技 - 北京开灵科技有限公司API百宝箱

企业抬头与税号查询

名字查税号、税号查名字,两个方向都支持,统一返回企业全称 + 纳税人识别号。 最典型的用途是开票时的抬头自动补全——用户敲「北京数影」,下拉列出候选,选中后全称和税号一起填进去,不用手输、也不会输错; 反过来,手里已有税号要回填抬头或做校验,直接用税号查即可。

🤖

给你的 AI 用 · 一键接入

把接入包复制给你的 AI(Claude / Cursor / 通义),它照着就能写出对接代码,含输入联想的防抖写法。

接口

POST  https://openapi.kailingteck.com/api/v1/enterprise/search

鉴权:X-App-Key + X-Timestamp(Unix 秒) + X-Sign(= sha256(appKey + 时间戳 + 报文原文 + appSecret) 小写十六进制)。与开灵其它接口完全一致。

请求参数

一个接口,两种查法。地址、鉴权都一样,区别只在于你传哪个字段:

① 知道名字,不知道税号

客户开票时只记得公司名的一部分 → 传 name,返回一批候选让他挑。

{ "name": "北京数影" }

→ 返回多条,让用户选一条

② 知道税号,要查名字

手里有税号,要回填抬头或做校验 → 传 tax_id,直接给你那一家。

{ "tax_id": "91110105MA01ECN70Q" }

→ 返回 1 条,或 0 条表示查无此号

★两个字段二选一,不能同时传,也不能都不传,否则返回 400。 返回里的 mode 会告诉你本次走的是哪一种。

字段必填大白话说明
name二选一★按名称模糊查:填企业名称关键词,2~64 个字符。3 字以上支持跨词匹配(「数影科技」能命中「北京数影互联科技有限公司」)
tax_id二选一★按税号精确查:填完整纳税人识别号,15~20 位数字或字母。小写会自动转大写,不用自己处理
limit选填最多返回几条,1~30,默认 30。按税号查只会返回 1 条,这个字段用不上

请求示例 · 按名称模糊查

{
  "name": "北京数影",
  "limit": 10
}

请求示例 · 按税号精确查

{
  "tax_id": "91110105MA01ECN70Q"
}

返回

统一信封 code/msg/requestId/timestamp/data,业务字段都在 data 里。

返回参数(data)

字段大白话说明
mode本次走的是哪种查法:name=按名称模糊查 / tax_id=按税号精确查
total本次返回的条数。按税号查命中就是 1,查不到就是 0
list[].company_name企业全称
list[].tax_id纳税人识别号(统一社会信用代码)
cachedtrue=命中平台缓存(结果一样,只是没再打上游)。注意:命中缓存同样计费
isMocktrue=演示数据,不是真实工商数据

返回示例(成功)

{
  "code": "CYT_00000",
  "msg": "success",
  "requestId": "cyt_xxx",
  "data": {
    "mode": "name",
    "total": 2,
    "list": [
      { "tax_id": "91310120MA1HYQR37H", "company_name": "上海和开灵科技中心" },
      { "tax_id": "91310120MABREQ9M6W", "company_name": "上海开灵辉盈商贸有限公司" }
    ],
    "cached": false,
    "isMock": false
  }
}

返回示例(按税号精确查)

{
  "code": "CYT_00000",
  "msg": "success",
  "data": {
    "mode": "tax_id",
    "total": 1,
    "list": [
      { "tax_id": "91110105MA01ECN70Q", "company_name": "北京数影互联科技有限公司" }
    ],
    "cached": false,
    "isMock": false
  }
}

返回示例(查不到)

{
  "code": "CYT_00000",
  "msg": "success",
  "data": { "mode": "tax_id", "total": 0, "list": [], "cached": false, "isMock": false }
}

异常与报错

情形含义与处理
400 · CYT_40001三种情况:name 和 tax_id 都没传/两个都传了/格式不对(name 不在 2~64 字,或 tax_id 不是 15~20 位)。读 data.hint 有具体原因
401 · CYT_40100 / 40102缺鉴权头,或签名算错
401 · CYT_40103时间戳与服务器相差超过 300 秒
403 · CYT_40301该密钥不是「企业开票名称模糊查询」产品的
429 · CYT_42901超过每分钟 120 次限流
502 · CYT_50200企业信息源暂时不可用。平台已自动重试过一次,仍失败才返回此码,稍后重试即可
查不到公司返回 total=0、list 为空数组。这是正常返回,不是错误,应允许用户手动输入

做输入联想时必看(否则费用会失控)

本接口按调用次数计费,调一次算一次。如果要做「边打字边联想」, 不做防抖的话用户填一次表可能触发几十次调用。三件事一定要做:

  1. 防抖:输入停止 300 毫秒后再发请求,不要每敲一个字就发
  2. 少于 2 个字不查:上游要求 name ≥ 2 字,少于 2 字直接不发
  3. 前端也留一层缓存:同一个词查过就别再查

平台侧已有 10 分钟服务端缓存,但那省的是上游额度,对你仍按调用次数计费,所以前端防抖才是真正省钱的地方。

let timer, lastQuery = '', memo = new Map();
input.oninput = () => {
  const kw = input.value.trim();
  clearTimeout(timer);
  if (kw.length < 2 || kw === lastQuery) return;   // 少于2字 / 重复词,不查
  if (memo.has(kw)) return render(memo.get(kw));   // 前端缓存
  timer = setTimeout(async () => {                 // 防抖 300ms
    lastQuery = kw;
    const r = await searchEnterprise(kw);
    memo.set(kw, r.data.list);
    render(r.data.list);
  }, 300);
};