DEVELOPER GUIDE · V1.0.0

把邮箱服务,接入你的系统。

从第一笔请求到验证码交付,完整接口、状态说明与可运行示例都在这里。

创建 API Key ↗
API BASE URLhttps://mail.jqiudata.com/v1
OpenAPI 3.1 ↗完整字段 · 导入工具 Postman ↓七个接口 · 默认只读 Markdown ↓完整文档 · 便于交接 Python ↓3.10+ · 无第三方依赖 Node.js ↓20+ · 原生 fetch
跳转到章节 / 接口

01 · 接入准备

版本 v1.0.0 · 邮箱单次接码 · 本文可直接交付第三方开发者。所有示例 UUID、邮箱、余额和验证码均为虚构,请以真实响应为准。

  1. 在工作台注册账户,完成钱包充值并等待管理员核实入账。提交充值申请本身不会增加余额。
  2. 在 /keys/ 创建 API Key,完整密钥只显示一次。每个账户最多保留 10 个有效密钥;撤销后立即失效。
  3. 从自己的服务端调用 MailDock,网页和 API 共用该账户的钱包与订单。不同客户应使用各自账户。
  4. 文档和下载无需登录;业务接口全部需要 Bearer Key。接单暂停时创建接口返回 ordering_paused,查询接口仍可使用。
项目约定
站点地址https://mail.jqiudata.com
API 前缀https://mail.jqiudata.com/v1
认证Authorization: Bearer <API_KEY>
请求 / 响应JSON / UTF-8;请求体使用 Content-Type: application/json
路径业务 API 不带结尾斜杠,例如 /v1/balance
金额十进制字符串,最多 8 位小数;保持字符串或用 Decimal,不用浮点计费
时间ISO 8601,包含时区;不要假定是本地时区
分页page 默认 1;每页固定 50;返回 items、page、page_size、total
BASH
export MAILDOCK_BASE_URL='https://mail.jqiudata.com'
# 通过终端交互输入或密钥管理器设置,不写入源代码。
read -r -s -p 'MailDock API Key: ' MAILDOCK_API_KEY; printf '\n'
export MAILDOCK_API_KEY
curl --fail-with-body --connect-timeout 10 --max-time 30 \
  "$MAILDOCK_BASE_URL/v1/balance" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

以上 shell 命令使用 Bash。API Key 只放 Authorization 请求头,不放 URL、前端脚本或公开仓库;本 API 用于服务端集成,不提供浏览器跨域 CORS 接入。使用 Bearer 时不需要 Cookie 或 CSRF Token。

02 · 从下单到拿到验证码

  1. 查询商品:GET /v1/products,选择目标服务与邮箱类型,保存商品 id 和 price。service 标识不能代替 product_id。
  2. 持久化业务请求:在自己的数据库保存业务单号、product_id、max_price 和唯一 Idempotency-Key,再发起 POST /v1/mail-orders。
  3. 取得订单:202 表示已冻结余额、开始分配;保存 order.id。email 为 null 时继续查订单,不要发起第二次购买。
  4. 取得邮箱:email 有值后,在需要验证的目标服务中使用该邮箱触发验证邮件。MailDock 不会代替业务方发起目标服务的验证流程。
  5. 取得验证码:轮询订单,code 不为 null 即可使用,保留大小写与前导零,并停止查码。不要等到 completed 才取 code。
  6. 未使用的订单可请求取消;只有取消确认及 settlement=released 才能确认冻结资金已释放。

此版本没有 Webhook。GET /v1/mail-orders 列表也返回完整订单对象,可用于多单合并查询。客户端停止轮询不会自动取消订单。

GET/v1/products

查询可售商品

仅返回已上架且最近库存大于零的商品;按名称、邮箱类型排序。报价通常每 2 分钟刷新,超过 5 分钟会阻止新下单。库存与报价可能在下单前变化。

参数位置必填说明
searchquery否服务名称或标识的包含匹配,忽略大小写,最多使用前 100 字。
domainquery否邮箱类型精确匹配,从目录返回值中选择。
pagequery否每页固定 50 项。默认 1;数值越界会限定到 1–100000;非整数返回 400。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X GET \
  "$MAILDOCK_BASE_URL/v1/products?search=Shopee&domain=gmail.com&page=1" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

响应示例 · HTTP 200

JSON
{
  "items": [
    {
      "id": "87c21967-8aa9-4496-9913-fb24b7a77691",
      "service": "ka",
      "name": "Shopee",
      "domain": "gmail.com",
      "price": "0.216",
      "unit": "余额点",
      "stock": 100,
      "quoted_at": "2026-11-14T10:00:00+00:00"
    }
  ],
  "page": 1,
  "page_size": 50,
  "total": 1
}

响应对象:ProductList。字段完整说明见下方数据字典;错误处理见错误码章节。

GET/v1/balance

查询钱包余额

网页与 API 共用账户余额。先冻结实际售价,验证码交付时扣费,确认未交付才释放冻结。

BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X GET \
  "$MAILDOCK_BASE_URL/v1/balance" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

响应示例 · HTTP 200

JSON
{
  "available": "10",
  "frozen": "0",
  "unit": "余额点"
}

响应对象:Balance。字段完整说明见下方数据字典;错误处理见错误码章节。

POST/v1/mail-orders

申请邮箱

202 仅表示订单已创建且余额已冻结,不代表邮箱已分配。用返回的订单 ID 轮询。200 表示相同幂等请求返回既有订单。max_price 是售价上限,实际冻结 order.price。

参数位置必填说明
Idempotency-Keyheader是8–100 个 ASCII 字符。同一账户按键去重。首次发送前持久化;超时重试沿用相同键和参数。建议 UUID。
JSON 字段类型说明(均必填)
product_idstring从商品目录取得的 UUID。
max_pricestring客户允许的最高售价,必须大于 0 且不超过 1000000000;建议使用刚查询的 price;十进制字符串,最多 8 位小数。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X POST \
  "$MAILDOCK_BASE_URL/v1/mail-orders" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data '{"product_id":"PRODUCT_UUID","max_price":"0.216"}'

先将 PRODUCT_UUID 替换为实际商品 UUID,将 IDEMPOTENCY_KEY 设为已持久化的业务请求键。200 重放响应中的 created=false,order 为既有订单的当前状态;下面展示首次 202。

响应示例 · HTTP 202

JSON
{
  "order": {
    "id": "25d47c44-59dc-4c54-a04f-dc5fd5eef222",
    "service": "ka",
    "service_name": "Shopee",
    "domain": "gmail.com",
    "email": null,
    "state": "creating",
    "state_label": "正在分配",
    "price": "0.216",
    "unit": "余额点",
    "settlement": "reserved",
    "code": null,
    "created_at": "2026-11-14T10:00:10+00:00",
    "expires_at": null,
    "received_at": null
  },
  "created": true
}

响应对象:CreateOrderResult。字段完整说明见下方数据字典;错误处理见错误码章节。

GET/v1/mail-orders

查询订单列表

仅当前账户订单,按创建时间倒序。每项为完整 Order,含邮箱与验证码;多笔订单可合并轮询列表。不支持 state 过滤。

参数位置必填说明
pagequery否每页固定 50 项。默认 1;数值越界会限定到 1–100000;非整数返回 400。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X GET \
  "$MAILDOCK_BASE_URL/v1/mail-orders?page=1" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

响应示例 · HTTP 200

JSON
{
  "items": [
    {
      "id": "25d47c44-59dc-4c54-a04f-dc5fd5eef222",
      "service": "ka",
      "service_name": "Shopee",
      "domain": "gmail.com",
      "email": "sample@example.com",
      "state": "received",
      "state_label": "验证码已送达",
      "price": "0.216",
      "unit": "余额点",
      "settlement": "captured",
      "code": "001234",
      "created_at": "2026-11-14T10:00:10+00:00",
      "expires_at": "2026-11-14T10:10:15+00:00",
      "received_at": "2026-11-14T10:01:00+00:00"
    }
  ],
  "page": 1,
  "page_size": 50,
  "total": 1
}

响应对象:OrderList。字段完整说明见下方数据字典;错误处理见错误码章节。

GET/v1/mail-orders/{order_id}

查询邮箱与验证码

邮箱尚未分配时 email 为 null;验证码尚未交付时 code 为 null。建议每 5 秒查询一次;先检查 code,再处理 state。

参数位置必填说明
order_idpath是属于当前账户的订单 UUID。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X GET \
  "$MAILDOCK_BASE_URL/v1/mail-orders/${ORDER_ID}" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

先设置 ORDER_ID 为创建接口返回的订单 UUID。

响应示例 · HTTP 200

JSON
{
  "order": {
    "id": "25d47c44-59dc-4c54-a04f-dc5fd5eef222",
    "service": "ka",
    "service_name": "Shopee",
    "domain": "gmail.com",
    "email": "sample@example.com",
    "state": "received",
    "state_label": "验证码已送达",
    "price": "0.216",
    "unit": "余额点",
    "settlement": "captured",
    "code": "001234",
    "created_at": "2026-11-14T10:00:10+00:00",
    "expires_at": "2026-11-14T10:10:15+00:00",
    "received_at": "2026-11-14T10:01:00+00:00"
  }
}

响应对象:OrderResult。字段完整说明见下方数据字典;错误处理见错误码章节。

POST/v1/mail-orders/{order_id}/cancel

取消未交付订单

无需请求体。HTTP 200 可能返回 cancel_requested,须继续查询至 canceled/released。重复取消已取消、失败或取消中的订单返回当前订单;已交付或待核对返回 409。取消与收码并发时可能仍交付并扣费。

参数位置必填说明
order_idpath是属于当前账户的订单 UUID。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X POST \
  "$MAILDOCK_BASE_URL/v1/mail-orders/${ORDER_ID}/cancel" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

先设置 ORDER_ID 为创建接口返回的订单 UUID。

响应示例 · HTTP 200

JSON
{
  "order": {
    "id": "25d47c44-59dc-4c54-a04f-dc5fd5eef222",
    "service": "ka",
    "service_name": "Shopee",
    "domain": "gmail.com",
    "email": "sample@example.com",
    "state": "cancel_requested",
    "state_label": "取消处理中",
    "price": "0.216",
    "unit": "余额点",
    "settlement": "reserved",
    "code": null,
    "created_at": "2026-11-14T10:00:10+00:00",
    "expires_at": null,
    "received_at": null
  }
}

响应对象:OrderResult。字段完整说明见下方数据字典;错误处理见错误码章节。

GET/v1/transactions

查询钱包流水

仅当前账户流水,按流水 ID 倒序。用 available_delta / frozen_delta 对账,不要把 reserve 与 capture 的 amount 重复计为消费。

参数位置必填说明
pagequery否每页固定 50 项。默认 1;数值越界会限定到 1–100000;非整数返回 400。
BASH
curl --fail-with-body --connect-timeout 10 --max-time 30 -X GET \
  "$MAILDOCK_BASE_URL/v1/transactions?page=1" \
  -H "Authorization: Bearer $MAILDOCK_API_KEY"

响应示例 · HTTP 200

JSON
{
  "items": [
    {
      "id": 1001,
      "kind": "reserve",
      "amount": "-0.216",
      "available_delta": "-0.216",
      "frozen_delta": "0.216",
      "available_after": "9.784",
      "frozen_after": "0.216",
      "note": "订单余额冻结",
      "created_at": "2026-11-14T10:00:10+00:00"
    }
  ],
  "page": 1,
  "page_size": 50,
  "total": 1
}

响应对象:TransactionList。字段完整说明见下方数据字典;错误处理见错误码章节。

03 · 幂等与重试:一笔业务只创建一个订单

Idempotency-Key 按账户隔离,长度 8–100 个 ASCII 字符,建议 UUID 或持久化业务单号。同一账户的不同 API Key 共用这个幂等范围。一次新的业务订单使用一个新键;同一业务的所有重试必须使用原键、原 product_id 和原 max_price。

情况正确处理
首次成功HTTP 202,created=true;保存 order.id。
同键同参数重放HTTP 200,created=false;返回既有订单的当前状态,不再次冻结或购买。
同键参数变化HTTP 409,idempotency_conflict;恢复原始参数取回已有订单,不用新键规避。
网络断开 / 超时 / 5xx / 非 JSON 网关响应结果可能已提交;退避后用完全相同的请求重放,直到取回订单或交由人工核对。
需要换商品或提价先确认原请求没有创建订单,再由业务决定是否建立新的业务请求;不要自动换键重买。

当前不会主动过期订单幂等键,客户不应复用历史键。订单列表不返回幂等键,也没有按幂等键查询的独立接口:丢失创建响应时,重新 POST 原请求即可取回订单。不要在每次 HTTP 重试时重新生成 UUID。

04 · 轮询、超时与限流

  1. 同一账户每分钟最多 120 个 API 请求,所有密钥与工作台 API 共用额度。每笔等待订单建议间隔至少 5 秒查询。
  2. 10 笔订单各每 5 秒查询一次已用满 120 次/分钟;并发多单应使用订单列表合并查询,或延长轮询间隔,为下单和取消预留额度。
  3. 最多同时存在 20 笔冻结余额的订单,review 中仍冻结的订单也占用名额。429 的具体原因以 error.code 区分。
  4. rate_limited 时遵守 Retry-After(当前 60 秒),配合退避和抖动。too_many_orders 应先等待结算或处理待核对订单,不能仅靠加快重试解决。
  5. expires_at 是预计等待截止时间,可能先进行最后一次查码和取消确认;时间经过不代表已经退款,以 state / settlement 和钱包为准。
  6. 本地等待超时后保留 order.id,之后继续查询或显式取消。review 且 code 为 null 时停止自动重购,联系平台核对。

05 · 订单状态与资金状态

state含义接入方动作
creating已冻结余额,正在分配邮箱等待 email,不重复购买
waiting邮箱已分配,等待验证邮件触发业务邮件并轮询 code
received验证码已交付并扣费,后台正在收尾使用 code,停止查码
completed订单处理完成可读取已交付 code
cancel_requested取消正在确认继续查询,不能认定已退款
canceled未交付,取消已确认检查 settlement=released
failed已确认分配失败,冻结已释放由业务决定后续处理
review处理结果需要人工核对先看 code;有值可使用,无值勿重买
settlement资金含义
reserved实际售价处于冻结中
captured验证码已交付,已扣费
released未交付,冻结已释放
refunded已扣费用经平台审核退回

正常流程为 creating → waiting → received → completed。取消与查码并发时,验证码可能先到并完成扣费;收到 HTTP 200 的取消响应不代表一定取消成功。review 可能保留已经交付的 code 与 captured/refunded,必须分别判断状态和资金。

06 · 价格、充值与对账

商品 price 是当前客户售价。max_price 只是允许的上限;订单按创建时的实际 order.price 冻结并锁价,之后商品变价不会改动历史订单。计价单位以 unit 为准。

事件 kindamountavailable_deltafrozen_delta
充值 topup(10)+10+100
冻结 reserve(0.216)-0.216-0.216+0.216
交付扣费 capture(0.216)-0.2160-0.216
未交付释放 release(0.216)+0.216+0.216-0.216
已扣费退款 refund(0.216)+0.216+0.2160

对账使用两类 delta 和对应 after 余额。冻结与扣费是两个事件,不能把所有 amount 相加当作支出;消费统计应依据 capture,退款依据 refund。流水当前不含 order_id;业务侧同时保存订单记录。

充值、退款核对和 API Key 管理在工作台完成,此版不提供第三方充值、自动支付或退款接口。不要依赖 /internal/ 路由,它们是网页会话接口。

07 · 错误码与恢复策略

JSON
{
  "error": {
    "code": "insufficient_balance",
    "message": "余额不足,请先充值。"
  }
}

按 HTTP 状态与 error.code 判断,不解析中文 message。路由、代理、403 CSRF 和意外 5xx 响应可能不是 JSON,客户端须兜底处理 HTTP 状态和响应文本。所有创建结果不明的重试都保留原幂等信息。

HTTPerror.code原因处理建议
400invalid_json请求体不是合法 JSON 对象。修正 JSON;金额用字符串。
400invalid_request字段缺失、类型错误或分页值无效。检查必填字段、UUID 和 page。
400invalid_amountmax_price 不在范围内或精度过高。金额大于 0、最多 8 位小数、不超过 1000000000。
400idempotency_required幂等键缺失或格式不符。提供 8–100 位 ASCII 幂等键。
401authentication_required未提供认证。在请求头携带 Bearer Key。
401invalid_authAuthorization 格式或认证方式不正确。使用大小写准确的 Bearer 前缀及一个空格。
401invalid_key密钥无效、已撤销或账户已停用。检查账户和密钥;不要持续重试。
404not_found记录不存在或不属于当前账户。核对订单 ID 与账户。UUID 路由格式无效时也可能返回非 JSON 404。
405method_not_allowedHTTP 方法不支持。按指定方法发送;路径末尾不加斜杠。
409insufficient_balance可用余额不足。完成钱包充值入账后再操作。
409unavailable_product商品无库存、已下架或不存在。重新查询目录,由业务决定商品。
409stale_quote商品报价超过有效时间。等待刷新后重新读取报价,确认价格。
409price_changed当前售价高于 max_price。重新确认价格;先核实旧请求未创建订单。
409idempotency_conflict同一键绑定的商品或价格参数不同。恢复首次请求原参数,取回既有订单;不要用新键绕过。
409already_delivered验证码已交付,不能取消。查询订单并读取已有 code。
409under_review订单等待人工核对。停止自动取消或重购,记录订单 ID 联系客服。
409conflict数据库操作冲突。查询现有记录;重放创建时保持同一键及参数。
429rate_limited同账户所有 Key 与网页 API 共用 120 次/分钟额度。遵守 Retry-After(当前 60 秒),降低总体并发。
429too_many_orders已有 20 笔冻结订单(含待核对订单)。等待订单结算或处理待核对订单;不要高频重试。
503ordering_paused平台暂停接单或尚未配置接单服务。等待平台恢复;已有订单仍可查询。
503worker_unavailable后台收码任务暂不可用。稍后重试;保持原幂等键和参数。
502provider_unavailable接码服务暂不可用。稍后重试;创建请求务必保留原幂等信息。

08 · Python / Node.js / Postman 示例

下载区提供 Python 3.10+ 标准库客户端和 Node.js 20+ fetch 客户端,无需额外依赖。默认执行只查询余额;申请邮箱必须显式指定商品、价格上限与事先保存的幂等键。示例不自动重买,也不会在等待超时后自动取消。

BASH
# 先设置 MAILDOCK_BASE_URL、MAILDOCK_API_KEY(见接入准备)。
python3 maildock_client.py balance
python3 maildock_client.py products --search Shopee --domain gmail.com
# 先保存以下幂等键和原请求参数;重试时保持三者不变。
python3 maildock_client.py create --product-id PRODUCT_UUID \
  --max-price '0.216' --idempotency-key YOUR_PERSISTED_REQUEST_ID
python3 maildock_client.py order ORDER_UUID
python3 maildock_client.py wait ORDER_UUID --timeout 600
python3 maildock_client.py cancel ORDER_UUID

# Node.js 默认只读余额;导入 MailDock 类后可调用其余方法。
node maildock_client.mjs

Postman:导入集合,在自己的本地环境设置 api_key;base_url 默认正式站点。手动选择商品后填写 product_id、max_price、idempotency_key。创建响应会自动保存 order_id;不要在重试前更换幂等键。集合默认只读:购买须设置 enable_order_requests=true;取消须填写 order_id 并设置 enable_cancel_requests=true。不要导出包含真实密钥的环境。

OpenAPI 3.1 可导入支持该版本的 Postman / Apifox / 客户端生成工具。金额 schema 为 string,code / email / 截止时间允许 null。只公开 /v1 业务接口。

09 · 上线自查

  1. 能通过 Bearer Key 查询余额与商品,失效 Key 返回 401;同账户额度统一管理。
  2. 首次发送前保存幂等键及请求,超时重放取回同一个 order.id;不会自动使用新键重买。
  3. 先等 email,再触发验证邮件;code 始终当字符串,支持前导零与字母。
  4. 正确处理 review、有 code 的 review、取消未确认和取消期间收码。
  5. 限流、非 JSON 响应、HTTP 超时均有处理;日志不记录 API Key 或完整验证码。
  6. 这是实际服务,无独立公共沙箱。联调先做查询;真实下单需要余额,会冻结资金并在交付时扣费。

数据字典 · Product

字段类型说明
idstring商品 UUID;申请邮箱时传 product_id。
servicestring服务标识,仅供展示与搜索;下单使用商品 UUID。
namestring目标服务名称。
domainstring邮箱类型。
pricestring当前每次接码的客户售价;十进制字符串,最多 8 位小数。
unitstring钱包计价单位,以响应为准。
stockinteger最近同步库存,不是下单保证。
quoted_atstring最近报价时间,带时区的 ISO 8601 字符串。

数据字典 · Balance

字段类型说明
availablestring可用余额;十进制字符串,最多 8 位小数。
frozenstring订单冻结余额;十进制字符串,最多 8 位小数。
unitstring计价单位;不要自行当作人民币或美元。

数据字典 · Order

字段类型说明
idstring订单 UUID,后续查询和取消使用此值。
servicestring订单锁定的服务标识。
service_namestring服务名称。
domainstring邮箱类型。
emailstring / null分配前为空;示例地址不是可用邮箱。
statestring订单处理状态。 可选值:creating, waiting, received, completed, cancel_requested, canceled, failed, review
state_labelstring状态中文文案;程序判断请使用 state。
pricestring创建时锁定的实际售价;十进制字符串,最多 8 位小数。
unitstring订单计价单位。
settlementstring资金状态,与处理状态分别判断。 可选值:reserved, captured, released, refunded
codestring / null尚未收到为空;可包含前导零、字母,不限定六位。有值即已交付,即使 state 为 review。
created_atstring订单创建时间。
expires_atstring / null分配后返回的预计等待截止时间;到期不等于即时退款。
received_atstring / null验证码交付时间。

数据字典 · Transaction

字段类型说明
idinteger账本流水 ID。
kindstring流水类型。 可选值:reserve, release, capture, topup, refund
amountstring本次事件的有符号金额;不可将所有事件直接相加当消费金额;十进制字符串,最多 8 位小数。
available_deltastring可用余额变化量;十进制字符串,最多 8 位小数。
frozen_deltastring冻结余额变化量;十进制字符串,最多 8 位小数。
available_afterstring事件后的可用余额;十进制字符串,最多 8 位小数。
frozen_afterstring事件后的冻结余额;十进制字符串,最多 8 位小数。
notestring流水说明。
created_atstring发生时间。
NEW ACTIVATION

申请邮箱

本次冻结

收码成功后扣费;未交付订单在取消确认后释放余额。

API KEY

密钥已创建

完整密钥仅在这里显示一次,请保存到安全的位置。