API 参考(/v1)
标准的 REST 接口,收发都是 JSON,功能和价格跟网页版一样。
基址与认证
基址:https://doouai.com/v1
认证:Authorization: Bearer doou_live_…
请求体:JSON(Content-Type: application/json),导入客户除外(multipart)
用哪个工作区、哪个组织由密钥决定,路径里不用写。/v1 不支持浏览器跨域调用,请从服务器端调。
快速开始
以「找 20 家德国的 LED 面板灯批发商」为例,流程是先报价,再开始搜索,然后隔一会儿取一次结果。下面三段代码做的是同一件事,挑你熟悉的语言就行。
curlexport DOOU=https://doouai.com/v1
export KEY=doou_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 余额(availableFen 可用,heldFen 进行中)
curl -s $DOOU/balance -H "Authorization: Bearer $KEY"
# 1. 报价(免费):20 家最多多少钱
curl -s -X POST $DOOU/searches/quote -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -d '{"quantity":20}'
# 2. 开始需求搜索(花钱);带 Idempotency-Key,网络超时重发不会重复扣费
curl -s -X POST $DOOU/searches -H "Authorization: Bearer $KEY" \
-H 'Content-Type: application/json' -H 'Idempotency-Key: crm-job-0001' \
-d '{"request":"LED 面板灯,找德国的批发商和分销商","quantity":20}'
# 202 {"runId":"…"};需求说不清 200 {"needsClarification":"…"};余额不够 402
# 3. 取结果:status 从 running 变成 completed,rows 是名单(name、domain、band 档位…),chargedFen 是实付
curl -s $DOOU/searches/<runId> -H "Authorization: Bearer $KEY"
Python(requests)import os, time, requests
API = "https://doouai.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['DOOU_API_KEY']}"}
quote = requests.post(f"{API}/searches/quote", json={"quantity": 20}, headers=HEADERS).json()
print("最多", quote["maxFen"] / 100, "元") # 先给人确认这个金额
run = requests.post(
f"{API}/searches",
json={"request": "LED 面板灯,找德国的批发商和分销商", "quantity": 20},
headers={**HEADERS, "Idempotency-Key": "crm-job-0001"},
).json()
while True:
result = requests.get(f"{API}/searches/{run['runId']}", headers=HEADERS).json()
if result["status"] != "running":
break
time.sleep(10)
for row in result["rows"]:
print(row["name"], row["domain"])
print("实付", (result["chargedFen"] or 0) / 100, "元")
Node.js 18+(自带 fetch)const API = 'https://doouai.com/v1';
const headers = { Authorization: `Bearer ${process.env.DOOU_API_KEY}`, 'Content-Type': 'application/json' };
const call = async (method, path, body, extra = {}) =>
(await fetch(API + path, { method, headers: { ...headers, ...extra }, body: body && JSON.stringify(body) })).json();
const quote = await call('POST', '/searches/quote', { quantity: 20 });
console.log('最多', quote.maxFen / 100, '元'); // 先给人确认这个金额
const run = await call('POST', '/searches', { request: 'LED 面板灯,找德国的批发商和分销商', quantity: 20 }, { 'Idempotency-Key': 'crm-job-0001' });
let result;
do {
await new Promise((r) => setTimeout(r, 10_000));
result = await call('GET', `/searches/${run.runId}`);
} while (result.status === 'running');
for (const row of result.rows) console.log(row.name, row.domain);
console.log('实付', (result.chargedFen ?? 0) / 100, '元');
调用限制
每把密钥单独算,同一个组织的所有密钥也合起来算,所以多建几把密钥绕不开限制。按最近一分钟统计。专业会员的所有限额都是 3 倍。
| 请求类型 | 每把密钥 / 分钟 | 每个组织合计 / 分钟 |
|---|
| 所有请求 | 60 | 300 |
| 其中调数据源或模型的(下面接口一览里标「花钱」的) | 10 | 30 |
超出时返回 429,响应头 Retry-After 是还要等几秒。
幂等请求(Idempotency-Key)
网络超时后重试花钱的请求,可能会重复扣费。给 POST、PATCH、DELETE 请求带上 Idempotency-Key(自己定一个 1–100 位的字符串)就能避免:24 小时内用同一把密钥、同一个键重发同样的请求,会直接拿到第一次的结果,不会再扣一次,响应头里有 Idempotent-Replayed: true。同一个键用在不同的请求上会返回 422。
错误码
出错时统一返回 {"error": "<代码>", "message": "<中文说明>"},程序看 error,message 可以直接给人看。
| HTTP 状态 | error | 说明 |
|---|
| 400 | bad_request | 参数不对 |
| 401 | invalid_api_key | 没带密钥、密钥不对或已吊销 |
| 402 | insufficient_balance | 余额不够(带 availableFen、neededFen),没开跑、没扣钱 |
| 403 | plan_required | 组织不是能用 API 的会员(或会员到期了)。密钥不吊销,开通或续上就能接着用 |
| 404 | not_found | 没有这个接口,或要的东西不在密钥的工作区 / 组织里 |
| 409 | quote_changed | 现在的报价超过你带的 maxFen(带现在的 maxFen),没开跑、没扣钱 |
| 409 | busy / signature_needed / … | 正在做,稍后再试;写开发信前要先在工作台确认一次落款 |
| 413 | too_large | 请求体太大(一般 64 KB,导入客户 5 MB) |
| 422 | idempotency_mismatch | 同一个 Idempotency-Key 用在了不同的请求上 |
| 429 | rate_limited / quota_exceeded | 太频繁(看 Retry-After 秒数)/ 额度用完 |
| 500 | internal | 我们出错了;花钱的操作中途出错不收钱 |
接口列表
一共 74 个。每个接口的请求和返回字段见 OpenAPI 文件。
账户
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /balance | 余额(单位分) | 免费 |
GET | /ledger | 账户流水(最近的在前) | 免费 |
GET | /members | 组织成员(分配负责人、待办用) | 免费 |
买家搜索
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /searches/quote | 买家搜索报价(免费) | 免费 |
POST | /searches | 需求搜索(花钱:最多报价的 maxFen,实付见结果) | 收费 |
GET | /searches | 买家搜索记录(含相似客户搜索、电商卖家搜索、广告主搜索;productId 只要为这个产品找的) | 免费 |
GET | /searches/{runId} | 一次买家搜索的进度与名单(运行中轮询它;电商卖家、广告主搜索的名单行带 seenOn) | 免费 |
POST | /similar | 相似客户搜索:给 1–5 个老客户官网,找同类的公司(花钱,报价同需求搜索) | 收费 |
电商卖家搜索
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /sellers/countries | 电商卖家搜索能查的国家与渠道 | 免费 |
POST | /sellers | 电商卖家搜索:在亚马逊、谷歌购物上卖这个产品的品牌与网店(花钱:最多报价的 maxFen,实付见结果) | 收费 |
广告主搜索
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /advertisers/countries | 广告主搜索能查的国家与平台 | 免费 |
POST | /advertisers | 广告主搜索:最近在 Facebook / Instagram、谷歌投这个产品广告的品牌(花钱:最多报价的 maxFen,实付见结果) | 收费 |
地图商家搜索
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /merchants/types | 地图商家搜索能选的商家类型(按零售门店、批发分销、工程安装分组) | 免费 |
POST | /merchants/suggest | 按产品挑商家类型(免费) | 免费 |
POST | /merchants | 地图商家搜索:Google 地图上卖这个产品的本地门店、批发商、工程商(花钱:最多报价的 maxFen,实付见结果) | 收费 |
海关查询
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /trade/quote | 海关查询报价(免费;产品先换成 HS 编码) | 收费 |
POST | /trade | 执行海关查询(花钱:最多按报价,实付见 chargedFen) | 收费 |
GET | /trade | 以前的海关查询(新的在前,最多 50 次,不含结果;productId 只要为这个产品查的,kind 只要这一种) | 免费 |
GET | /trade/{runId} | 看以前的一次海关查询 | 免费 |
联系人
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /companies/{companyId}/contacts | 一家公司的联系方式与已知的人(公司要在这个工作区的名单或客户库里) | 免费 |
POST | /companies/{companyId}/channels | 再找一遍公司联系方式(免费) | 收费 |
POST | /companies/{companyId}/contacts/quote | 找联系人报价(免费:找人不收钱,查邮箱 / 手机才收) | 收费 |
POST | /companies/{companyId}/contacts | 查联系人的邮箱 / 手机(花钱:没找到不收,查到过的不再收;实付见 chargedFen) | 收费 |
邮箱验证
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /verify/quote | 邮箱验证报价(免费) | 免费 |
POST | /verify | 邮箱验证(花钱:最多报价的 maxFen;结果不明、没验成的不收) | 收费 |
GET | /verify/{batchId} | 一批邮箱验证(运行中轮询它:验完一个出一个结论) | 免费 |
查一家公司
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /companies/resolve | 查一家公司:官网、邮箱或公司名 → 认出是哪一家(免费) | 收费 |
GET | /companies/{companyId} | 一家公司(不在客户库也能看:找到过的、海关查询或求购信息里认出的;别的 404) | 免费 |
客户库
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /library | 客户库列表(筛选、排序,一页 50) | 免费 |
POST | /library | 加进客户库(免费):海关查询、竞品画像、求购信息里认出来的,或手动新建(必须有官网) | 免费 |
POST | /library/import | 导入客户(.xlsx / .csv,multipart 字段 file,≤ 5 MB、≤ 2,000 行;查询参数 dryRun=true 只预览;客户库满了超出的跳过并说明) | 免费 |
GET | /library/export | 导出 Excel(公司、联系人两张表;筛选同列表,不分页,最多 5,000 家) | 免费 |
GET | /library/stats | 客户报表(阶段分布、来源效果、近 8 周、按负责人) | 免费 |
GET | /search | 全局搜索:客户库里的公司、联系人、做过的搜索(每类最多 5 条) | 免费 |
POST | /companies/{companyId}/feedback | 标「不相关」:这家以后不再给这个产品(按组织) | 收费 |
DELETE | /companies/{companyId}/feedback | 撤销「不相关」(按组织;当时加进产品卡的排除词也拿掉;没说过也 204) | 免费 |
GET | /library/{companyId} | 看客户库里的一家 | 免费 |
PATCH | /library/{companyId} | 改跟进(阶段、标签、备注、负责人、重点客户;只改带了的;改阶段自动记一条跟进) | 免费 |
GET | /library/{companyId}/activities | 跟进记录(新的在前) | 免费 |
POST | /library/{companyId}/activities | 记一条跟进 | 免费 |
DELETE | /library/{companyId}/activities/{activityId} | 删一条跟进(只能删自己记的;系统记的不能删) | 免费 |
POST | /library/{companyId}/people | 手动记一个联系人(只在这个工作区) | 免费 |
GET | /people | 联系人(付过钱查到的 + 手动记的;一页 50) | 免费 |
PATCH | /people/{personKey} | 改手动记的联系人 | 免费 |
DELETE | /people/{personKey} | 删手动记的联系人 | 免费 |
待办
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /tasks | 待办(status、when=overdue|today|week、assignee=me|<userId>、companyId) | 免费 |
POST | /tasks | 建待办(不给负责人就是密钥的建立人) | 免费 |
PATCH | /tasks/{taskId} | 改待办 / 打勾做完 | 免费 |
DELETE | /tasks/{taskId} | 删待办 | 免费 |
我的产品
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /products | 我的产品(组织卖的东西,改过的在前) | 免费 |
POST | /products | 加一个产品(组织内不重名,最多 50 个) | 免费 |
PATCH | /products/{productId} | 改产品(只改带了的;可空的文字字段传 null 清空,列表传 [] 清空) | 免费 |
DELETE | /products/{productId} | 删产品 | 免费 |
POST | /products/ensure | 按名字取或建一个产品(同名的给已有的那个) | 免费 |
POST | /products/{productId}/understand | 产品卡:把产品名理解成几种(免费),选一个确认 | 收费 |
POST | /products/{productId}/card | 确认产品卡:选一个理解(optionId),或给改好的整张卡 | 免费 |
国家进口榜单
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /markets/quote | 国家进口榜单报价(免费) | 免费 |
POST | /markets | 做一份国家进口榜单(每月 1 份不收钱;要收钱的先报价,带 maxFen 开始) | 收费 |
GET | /markets | 国家进口榜单列表(productId 只要为这个产品做的) | 免费 |
GET | /markets/{reportId} | 一份国家进口榜单(运行中轮询它) | 免费 |
买家评论分析
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /reviews/quote | 买家评论分析报价(免费) | 免费 |
POST | /reviews | 买家评论分析:一个品类(或一个商品)的买家抱怨什么、夸什么、常问什么(花钱:最多报价的 maxFen,什么都没归纳出来不收) | 收费 |
GET | /reviews | 买家评论分析记录(productId 只要为这个产品做的;不含商品与主题) | 免费 |
GET | /reviews/{reportId} | 一份买家评论分析(运行中轮询它) | 免费 |
GET | /reviews/countries | 买家评论分析能看的亚马逊站 | 免费 |
写开发信
| 方法 | 路径 | 说明 | 计费 |
|---|
POST | /outreach/drafts | 写开发信(免费;只写不发):按这家的情况写第一次联系的信,带中文对照 | 收费 |
客户动态
| 方法 | 路径 | 说明 | 计费 |
|---|
GET | /watches | 关注与订阅(关注的客户、同行,需求订阅,求购帖订阅;productId 只要为这个产品订阅的) | 免费 |
POST | /watches | 关注一家客户、一个同行,或订阅(需求订阅、求购帖订阅:每周查一次,最多花 weeklyCapFen) | 免费 |
PATCH | /watches/{watchId} | 暂停 / 恢复,改订阅的每周上限 | 免费 |
DELETE | /watches/{watchId} | 取消关注 / 订阅(连它的动态一起删) | 免费 |
GET | /signals | 客户动态(一页 50;unread、kind、watchId、companyId 筛) | 免费 |
POST | /signals/read | 标已读(ids,或 all: true) | 免费 |
POST | /signals/{signalId}/task | 动态转待办(挂这家公司,标题是建议做的事;转过的回原来那条) | 免费 |
GET | /posts/{runId} | 一次求购信息:求购帖订阅查到的新帖子(动态 new_posts 的 runId) | 免费 |
版本与兼容
/v1 里已有的字段不会删、不会改名、不会改类型。如果哪天必须做不兼容的改动,会另开 /v2。以后可能会加新字段,碰到不认识的字段忽略就好。