企业工商信息查询 API 实战详解:一次 GET 请求拿到工商全字段(Python / Go / JS / PHP 多语言示例)
企业工商信息查询 API 实战详解:一次 GET 请求拿到工商全字段(Python / Go / JS / PHP 多语言示例)

摘要:企业工商信息查询 API 是一个通过「企业名称关键词」检索工商档案的 HTTP 接口。一次
GET请求即可返回最匹配的前 5 家企业,覆盖企业全称、法定代表人、注册资本、统一社会信用代码、经营范围、注册地址、联系方式等 19 个核心字段,数据来源于权威工商数据库并按 6 小时缓存。本文从接口能力、认证配额、请求/响应结构、错误码、多语言调用到工程化封装,完整讲清楚如何把它接入到 KYC、风控、获客与供应商核验等业务中。
工商信息是企业实名核验(KYC)、风控反欺诈、供应商背调和销售线索补全的基础数据。自建工商数据采集与清洗成本高、合规风险大,因此大多数业务会选择直接调用成熟的工商信息查询接口。本文以一个标准的「企业工商信息查询 API」为例,系统讲解它的设计、调用方式与落地实践。
一、接口能做什么
这是一个 按企业名称模糊检索工商信息 的只读查询接口。它的核心特征可以用一句话概括:输入一个企业名称关键词,输出最匹配的前 5 家企业的完整工商档案。
| 能力项 | 说明 |
|---|---|
| 接口标识 | company-search |
| 接口地址 | https://v1.apizero.cn/api/company-search |
| 请求方法 | GET |
| 分类 | KYC / 企业数据 |
| 返回条数 | 最多 5 条(按上游匹配评分排序) |
| 字段覆盖 | 19 个工商核心字段 |
| 数据时效 | 6 小时缓存 |
| QPS 限制 | 5 次/秒 |
与「按统一社会信用代码精确查询单家企业」的接口不同,本接口偏向 搜索(search)语义:它接受一个不那么精确的关键词(如「腾讯科技」「阿里巴巴」),返回一组候选企业,并通过 match_field 字段告诉你每一条是因为「公司名称匹配」「历史名称」还是「股东信息」命中的。这使它特别适合「用户只记得大概名字」「需要消歧选择正确主体」的场景。
二、典型应用场景
工商查询接口看似简单,但它是很多业务链路的第一环。常见落地场景包括:
- 实名核验 / KYC:注册或入驻环节,根据用户填写的公司名校验企业是否真实存在、登记状态是否「存续」,并回填统一社会信用代码。
- 风控与反欺诈:结合注册资本、成立时间、登记状态判断企业经营风险;对「注销」「吊销」状态的主体进行拦截或人工复核。
- 供应商 / 合作方背调:签约前快速核对对方主体资质、法人、注册地址,避免与空壳或异常主体合作。
- 销售线索补全(CRM):销售只录入了公司简称,自动补全企业全称、行业分类、所在城市、联系方式,提升线索质量。
- 批量数据清洗:对历史客户表中残缺、口语化的公司名进行标准化,统一成工商登记的规范全称。
这些场景的共同点是:只需要关键词就能发起查询,并希望一次拿到结构化、可直接入库的字段。
三、认证与配额
接口支持匿名调用和带 Key 调用两种模式,区别只在于额度与频率:
| 模式 | QPS | 每日额度 | 适用 |
|---|---|---|---|
| 匿名(不带 Key) | 1 | 20 次/日 | 功能验证、临时试跑 |
| 带 API Key | 5 | 500 次/日 | 正式集成、生产环境 |
由于工商数据属于商业敏感信息,生产环境建议带 Key 调用。API Key 在 https://apizero.cn/account/keys 申请后获取。
鉴权方式是把 Key 放在请求头 X-API-Key 中:
GET /api/company-search?name=腾讯科技 HTTP/1.1
Host: v1.apizero.cn
X-API-Key: YOUR_API_KEY
工程建议:优先用请求头
X-API-Key传递密钥,而不是写在 URL 查询参数里。URL 容易出现在网关日志、浏览器历史和 Referer 中,密钥放在 Header 更安全。接口同时兼容?key=查询参数方式,便于快速调试。
四、请求说明
4.1 请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 是 | 企业名称关键词,长度 2~50 个字符,例如「腾讯科技」「阿里巴巴」 |
4.2 请求头
| Header | 类型 | 必填 | 说明 |
|---|---|---|---|
X-API-Key |
string | 否 | API Key;不传则走匿名额度 |
参数规则很克制,只有一个 name。需要注意的是长度约束:少于 2 个字符或超过 50 个字符都会被判为参数错误(错误码 4000),因此在发起请求前最好先做一次本地校验和 trim()。
五、多语言调用示例
下面给出 5 种语言的可运行示例,均使用请求头方式鉴权,把 YOUR_API_KEY 替换为实际申请到的 Key 即可。
5.1 cURL
curl -G "https://v1.apizero.cn/api/company-search" \
--data-urlencode "name=腾讯科技" \
-H "X-API-Key: YOUR_API_KEY"
5.2 Python
import requests
resp = requests.get(
"https://v1.apizero.cn/api/company-search",
params={"name": "腾讯科技"},
headers={"X-API-Key": "YOUR_API_KEY"},
timeout=15,
)
resp.raise_for_status()
data = resp.json()
if data["code"] == 0:
for item in data["data"]["list"]:
print(item["name"], item["credit_code"], item["reg_status"])
else:
print("查询失败:", data["code"], data["msg"])
5.3 JavaScript(Node.js 18+ / 浏览器)
const params = new URLSearchParams({ name: "腾讯科技" });
const res = await fetch(
`https://v1.apizero.cn/api/company-search?${params}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
if (data.code === 0) {
data.data.list.forEach((c) =>
console.log(c.name, c.credit_code, c.reg_status)
);
}
5.4 Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://v1.apizero.cn/api/company-search", nil)
q := req.URL.Query()
q.Set("name", "腾讯科技")
req.URL.RawQuery = q.Encode()
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
5.5 PHP
<?php
$url = "https://v1.apizero.cn/api/company-search?" . http_build_query([
"name" => "腾讯科技",
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: YOUR_API_KEY"]);
$body = curl_exec($ch);
curl_close($ch);
$data = json_decode($body, true);
print_r($data);
六、响应结构详解
6.1 响应示例
{
"code": 0,
"msg": "成功",
"data": {
"keyword": "腾讯科技",
"total": 20,
"list": [
{
"id": 1466562059,
"name": "广州腾讯科技有限公司",
"logo": "https://img5.tianyancha.com/logo/lll/...",
"english_name": "Guangzhou Tencent Technology Co., Ltd.",
"history_names": "",
"legal_person": "邬红波",
"establish_time": "2014-12-31",
"reg_capital": "7000万人民币",
"reg_status": "存续",
"credit_code": "91440101327598294H",
"business_scope": "电子;通信与自动控制技术研究...",
"reg_location": "广州市海珠区新港中路397号...",
"phone": "020-81167888",
"email": "service@tencent.com",
"category": "研究和试验发展",
"city": "广州市",
"district": "海珠区",
"company_org_type": "有限责任公司",
"match_field": "股东信息"
}
]
},
"request_id": "mota..."
}
6.2 字段说明
顶层结构为 code / msg / data / request_id,其中 data.list 是企业数组,单条企业的字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
keyword |
string | 查询关键词回显 |
total |
number | 上游命中总数(最多返回前 5 条) |
list[].id |
number | 企业 ID,可用于后续详情跳转 |
list[].name |
string | 企业全称 |
list[].logo |
string | 企业 LOGO 图片 URL(可能为空) |
list[].english_name |
string | 英文名(可能为空) |
list[].history_names |
string | 曾用名(可能为空) |
list[].legal_person |
string | 法定代表人 |
list[].establish_time |
string | 成立日期,格式 YYYY-MM-DD |
list[].reg_capital |
string | 注册资本(含币种,如「7000万人民币」) |
list[].reg_status |
string | 登记状态(存续 / 注销 / 吊销 等) |
list[].credit_code |
string | 统一社会信用代码(18 位) |
list[].business_scope |
string | 经营范围 |
list[].reg_location |
string | 注册地址 |
list[].phone |
string | 联系电话(取首项) |
list[].email |
string | 联系邮箱(取首项) |
list[].category |
string | 行业分类 |
list[].city |
string | 所在城市 |
list[].district |
string | 所在区/县 |
list[].company_org_type |
string | 企业类型(如「有限责任公司」) |
list[].match_field |
string | 命中字段(公司名称匹配 / 股东信息 / 历史名称 等) |
有两个字段在工程中尤其值得关注:
total是上游命中的总数,而list最多只返回 5 条。也就是说,当total远大于 5 时,说明关键词过于宽泛,应提示用户补全更完整的名称。match_field解释了「为什么这家企业会被匹配出来」。当它不是「公司名称匹配」时(例如「股东信息」「历史名称」),需要谨慎判断是否为用户真正想找的主体。
字段中的 logo、english_name、history_names、phone、email 等都可能为空字符串,入库与展示时必须做空值兜底。
七、错误码与异常处理
接口通过顶层 code 表达业务状态,0 为成功,非 0 为各类错误:
| code | 含义 | 处理建议 |
|---|---|---|
0 |
成功 | 正常解析 data |
4000 |
参数错误(name 缺失 / 长度不足 2 / 超过 50) | 请求前本地校验并修正 |
4011 |
API Key 无效 | 检查 Key 是否填写正确 |
4013 |
API Key 已暂停 | 联系账户管理员恢复 |
4014 |
当前 IP 不在 Key 白名单内 | 调整 Key 的 IP 白名单 |
4022 |
余额不足 | 充值或切换额度 |
4029 |
QPS 限流 | 降低并发,指数退避后重试 |
4030 |
今日免费额度已用完 | 次日重置或升级额度 |
4044 |
未找到匹配企业 | 作为空结果处理,不算异常 |
5020 |
上游不可用(回源失败 / 数据异常) | 短暂退避后重试 |
5030 |
上游凭据未配置(运维问题) | 重试无效则上报 |
异常处理有三条经验值得遵循:
- 区分「业务空结果」和「调用失败」。
4044表示确实没查到企业,应当当作合法的空结果返回给上层,而不是抛异常。 - 对限流和上游错误做退避重试。
4029、5020属于可恢复错误,适合「指数退避 + 最大重试次数」策略;而4000、4011属于不可恢复错误,重试没有意义。 - 记录
request_id。 响应里的request_id是排查问题的关键凭证,建议随业务日志一并落库。
八、工程实践与最佳实践
8.1 善用 6 小时缓存
接口数据按 6 小时缓存。这意味着同一关键词在 6 小时内多次查询,上游数据不会变化。因此在客户端再叠加一层本地缓存(例如以 name 为 key、TTL 设为 1~6 小时)可以显著降低调用次数、规避日额度限制,对「批量清洗历史数据」尤其有效。
8.2 关键词规范化
发请求前对 name 做规范化能明显提升命中质量:去除首尾空格、过滤特殊符号、统一全角半角括号。对于用户输入的简称,可先以简称查询,再用返回结果中的 name(全称)作为后续精确处理的依据。
8.3 限流与退避
QPS 上限为 5,批量任务必须自己做节流(令牌桶或固定间隔)。遇到 4029 时不要立即重试,而是按 1s → 2s → 4s 退避,并设置最大重试次数,避免雪崩。
8.4 合规使用
工商信息虽属公开登记数据,但 phone、email、legal_person 等字段涉及个人信息。落地时应遵循「最小必要」原则,仅在合法合规的业务场景中使用,并对敏感字段做好访问控制与脱敏展示。
九、实战:一个可复用的 Python 客户端
把上面的最佳实践(本地缓存、参数校验、限流退避、错误映射)封装成一个客户端类,即可直接用于生产:
import time
import threading
import requests
class CompanySearchError(Exception):
"""不可恢复的业务错误。"""
def __init__(self, code, msg):
super().__init__(f"[{code}] {msg}")
self.code = code
self.msg = msg
class CompanySearchClient:
BASE_URL = "https://v1.apizero.cn/api/company-search"
# 可重试的错误码:QPS 限流、上游临时不可用
RETRYABLE = {4029, 5020, 5030}
def __init__(self, api_key: str = "", cache_ttl: int = 3600, qps: int = 5):
self.api_key = api_key
self.cache_ttl = cache_ttl
self._min_interval = 1.0 / max(qps, 1)
self._cache = {}
self._last_call = 0.0
self._lock = threading.Lock()
self._session = requests.Session()
def _throttle(self):
with self._lock:
wait = self._min_interval - (time.time() - self._last_call)
if wait > 0:
time.sleep(wait)
self._last_call = time.time()
def search(self, name: str, max_retry: int = 3):
name = (name or "").strip()
if not (2 <= len(name) <= 50):
raise CompanySearchError(4000, "name 长度需在 2~50 字符之间")
cached = self._cache.get(name)
if cached and time.time() - cached[0] < self.cache_ttl:
return cached[1]
headers = {"X-API-Key": self.api_key} if self.api_key else {}
backoff = 1.0
for attempt in range(max_retry + 1):
self._throttle()
resp = self._session.get(
self.BASE_URL, params={"name": name}, headers=headers, timeout=15
)
payload = resp.json()
code = payload.get("code")
if code == 0:
result = payload["data"]["list"]
self._cache[name] = (time.time(), result)
return result
if code == 4044: # 没查到,按空结果处理
return []
if code in self.RETRYABLE and attempt < max_retry:
time.sleep(backoff)
backoff *= 2
continue
raise CompanySearchError(code, payload.get("msg", "未知错误"))
raise CompanySearchError(4029, "重试次数耗尽")
if __name__ == "__main__":
client = CompanySearchClient(api_key="YOUR_API_KEY")
for company in client.search("腾讯科技"):
print(f"{company['name']} | {company['credit_code']} | {company['reg_status']}")
这个封装实现了:参数前置校验、按 QPS 节流、对可恢复错误指数退避重试、对 4044 空结果优雅降级、本地 TTL 缓存,以及把不可恢复错误统一抛成自定义异常,便于上层捕获。
十、常见问题(FAQ)
Q:不申请 Key 能用吗?
可以。匿名模式下 QPS 为 1、每日 20 次,适合功能验证;正式集成建议带 Key,额度提升到 QPS 5、每日 500 次。
Q:一次为什么只返回 5 条?
接口按上游匹配评分排序后取最相关的前 5 条。响应里的 total 会告诉你命中的总数;若 total 很大,说明关键词太宽泛,应补全更完整的企业名称。
Q:能用统一社会信用代码精确查吗?
本接口是按 name 关键词搜索的,输入是企业名称。信用代码会在返回结果的 credit_code 字段中给出,可用于后续的精确核验。
Q:数据多久更新一次?
数据按 6 小时缓存,同一关键词在缓存窗口内结果稳定。对实时性要求不高的场景,建议在客户端再加一层本地缓存。
Q:查不到企业会报错吗?
不会抛系统异常,而是返回错误码 4044,应当作为「空结果」处理。
Q:match_field 有什么用?
它表示这条结果是凭哪个字段命中的(公司名称匹配 / 股东信息 / 历史名称等)。当命中来源不是公司名称时,需要结合业务判断是否为目标主体。
十一、小结
企业工商信息查询 API 的设计非常聚焦:一个 name 参数、一个 GET 请求、最多 5 条结构化结果。它把工商数据采集、清洗、匹配排序等复杂工作收敛到一次标准 HTTP 调用背后,让 KYC、风控、获客与供应商核验等业务可以快速接入。
落地时的关键点可以归纳为四句话:用请求头传 Key 更安全;用 total 判断关键词是否过宽;用 match_field 判断主体是否匹配;用缓存 + 退避重试扛住额度与限流。把这些做扎实,工商查询就能成为业务链路里稳定可靠的一环。
更多推荐
所有评论(0)