多平台复用路线 API

这一组只给 Cursor/Claude/Poe 等多平台注册机使用,接口统一在 /api/reuse/v1/* 下。

文档入口 返回控制台

AI 快速接入

你要接入 MailOps 多平台复用 API。

BASE_URL = "http://ops.nanlizz.top"
API_KEY = "mak_xxx"
PLATFORM = "cursor"  # 必须显式传平台;例如 cursor/claude/poe/自定义平台

所有请求都带:
Authorization: Bearer API_KEY
Content-Type: application/json

固定流程:
1. 按平台预留邮箱:
   POST {BASE_URL}/api/reuse/v1/mail/reserve
   body: {"platform":PLATFORM,"request_id":"batch-worker-attempt","lease_seconds":1800}
2. 如果返回 email 为空,表示该平台当前没有可复用邮箱。
3. 用返回的 email 去目标平台注册,并且只轮询这个 email 的验证码。
4. 查询验证码仍然用现有邮件接口:
   GET {BASE_URL}/api/mail/code?email={email}&keyword=code,验证码,verification code,{PLATFORM}&limit=10&folders=inbox,junk
5. 注册成功或平台可能已经占用邮箱时,确认平台占用:
   POST {BASE_URL}/api/reuse/v1/mail/mark-used
   body: {"platform":PLATFORM,"email":email,"lease_token":lease_token,"login_email":"平台登录邮箱","account":{...}}
6. 只有明确没有占用该邮箱时才释放:
   POST {BASE_URL}/api/reuse/v1/mail/release
   body: {"platform":PLATFORM,"email":email,"lease_token":lease_token,"reason":"register failed before email accepted"}

禁止事项:
- 不要省略 platform。多平台注册机必须显式传平台名。
- 不要用 GET /api/mailboxes 或 GET /api/reuse/v1/summary 来分配邮箱,它们只是查看/诊断。
- 不要丢 lease_token;mark-used/release 必须带 reserve 返回的 token。
- 同一个平台已 success 的邮箱不会再次发给同平台。

机器可读规格:/api-spec-reuse.json

状态流转

阶段接口平台状态调用方要求
查看平台GET /api/reuse/v1/platforms不改变启动时可读取支持的平台和策略。
可视化/排查GET /api/reuse/v1/summary不改变只用于页面或诊断,不用于分配。
预留邮箱POST /api/reuse/v1/mail/reservereserved保存 emaillease_tokenrequest_id
平台注册成功POST /api/reuse/v1/mail/mark-usedsuccess必须带正确 lease_token;可带平台账号资料。
失败且未占用POST /api/reuse/v1/mail/releasereleased只有确认目标平台没接受这个邮箱时才释放。
失败但可能占用POST /api/reuse/v1/mail/mark-usedsuccess建议 status=needs_review 并写清失败阶段。

接口明细

1. 平台列表

GET /api/reuse/v1/platforms
{
  "ok": true,
  "platforms": [
    {"platform_key": "openai", "display_name": "OpenAI", "allow_reuse": 0},
    {"platform_key": "cursor", "display_name": "Cursor", "allow_reuse": 1}
  ]
}

2. 状态汇总

GET /api/reuse/v1/summary?platform=cursor&search=outlook&page=1&limit=50

summary 只用于页面和排查。OpenAI 卡片是旧链路可取口径;Cursor/Claude/Poe 是多平台复用口径。

3. 预留邮箱

POST /api/reuse/v1/mail/reserve
Authorization: Bearer mak_xxx
Content-Type: application/json

{
  "platform": "cursor",
  "request_id": "batch-20260625-worker-01-attempt-0001",
  "lease_seconds": 1800
}
成功:
{
  "ok": true,
  "platform": "cursor",
  "email": "legacy-used@outlook.com",
  "lease_token": "lease_xxx",
  "lease_expires_at": "2026-06-25T10:30:00.000Z",
  "consumed": false
}

没有可用邮箱:
{
  "ok": true,
  "platform": "cursor",
  "email": "",
  "mailbox": null,
  "reason": "no_available"
}

4. 确认平台已用

POST /api/reuse/v1/mail/mark-used
Authorization: Bearer mak_xxx
Content-Type: application/json

{
  "platform": "cursor",
  "email": "legacy-used@outlook.com",
  "lease_token": "lease_xxx",
  "login_email": "cursor-login@example.com",
  "status": "available",
  "account": {"batch_id": "batch-001"},
  "detail": {"stage": "registered", "worker": "worker-01"}
}

5. 释放租约

POST /api/reuse/v1/mail/release
Authorization: Bearer mak_xxx
Content-Type: application/json

{
  "platform": "cursor",
  "email": "legacy-used@outlook.com",
  "lease_token": "lease_xxx",
  "reason": "target rejected before email accepted"
}

选号规则

规则说明
同平台不重复同一邮箱在同一 platform 已经 reservedsuccess 时,不会再次发给该平台。
跨平台可复用邮箱已经是 OpenAI 旧链路已用,只要健康正常,仍可发给 Cursor/Claude/Poe 等其他平台。
OpenAI 保护OpenAI 不走复用逻辑,旧 GPT 注册机继续使用 /api/mailboxes/*
健康过滤跳过 code_health=no_code/blocked/unhealthycategory=no_code/invalid/error
租约防串号mark-used/release 必须携带正确 lease_token;错误 token 返回 409

Python 示例

import time
import requests

BASE = "http://ops.nanlizz.top"
KEY = "mak_xxx"
PLATFORM = "cursor"
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}

reserved = requests.post(
    f"{BASE}/api/reuse/v1/mail/reserve",
    headers=HEADERS,
    json={"platform": PLATFORM, "request_id": "batch-001-worker-01-attempt-001", "lease_seconds": 1800},
    timeout=30,
).json()

if not reserved.get("email"):
    raise RuntimeError(f"{PLATFORM} 没有可复用邮箱")

email = reserved["email"]
lease_token = reserved["lease_token"]

# 把 email 提交给目标平台,然后只轮询这个 email。
deadline = time.time() + 180
while time.time() < deadline:
    code = requests.get(
        f"{BASE}/api/mail/code",
        headers=HEADERS,
        params={"email": email, "keyword": f"code,验证码,verification code,{PLATFORM}", "limit": 10, "folders": "inbox,junk"},
        timeout=30,
    ).json()
    if code.get("found"):
        break
    time.sleep(8)
else:
    requests.post(
        f"{BASE}/api/reuse/v1/mail/release",
        headers=HEADERS,
        json={"platform": PLATFORM, "email": email, "lease_token": lease_token, "reason": "code timeout before account created"},
        timeout=30,
    )
    raise RuntimeError("验证码超时")

requests.post(
    f"{BASE}/api/reuse/v1/mail/mark-used",
    headers=HEADERS,
    json={
        "platform": PLATFORM,
        "email": email,
        "lease_token": lease_token,
        "login_email": "cursor-login@example.com",
        "status": "available",
        "account": {"batch_id": "batch-001"}
    },
    timeout=30,
).raise_for_status()