API 文档
YYDS Mail 提供面向外部集成的 RESTful API。当前文档按六个主题组织核心接入说明,并额外补充仍然公开可调用的查询接口。所有接口都以 /v1 为前缀。
快速开始
- 通过 GitHub 或 LinuxDo OAuth 在 /login 登录
- 前往 API Key 管理 创建密钥
- 在请求头中使用
X-API-Key进行 API 调用
curl https://maliapi.215.im/v1/accounts \ -X POST \ -H "X-API-Key: AC-your_api_key"
基础 URL
https://maliapi.215.im/v1认证方式
Bearer Token (JWT)
通过 OAuth 登录获取的 JWT 访问令牌。
Authorization: Bearer <access_token>API Key
以 AC- 前缀开头的 API Key,适用于自动化调用;owner 侧 `/v1/me/domains*` 和 `/v1/me/wildcard-rules*` 管理入口要求 Bearer JWT。
X-API-Key: AC-...临时 Token
创建临时邮箱时返回的短期有效令牌。
Authorization: Bearer <temp_token>公开查询接口
以下接口仍属于公开可调用范围,适合在匿名查询、套餐展示、公开统计和文档发现中使用。
GET /v1/domains GET /v1/plans GET /v1/pricing GET /v1/domain-reward/config GET /v1/stats
临时邮箱 API
创建一次性邮箱,无需注册。邮件在 24 小时后自动删除。
/v1/accounts创建临时邮箱。既支持普通域名,也支持通过泛子域名创建真实子域邮箱。
请求规则
- 固定域名场景传 `domain`。
- 泛子域名场景继续传 `domain`,再额外传一个可选的 `subdomain`。
- `localPart` 是推荐字段;旧字段 `address` 仍兼容。
- `subdomain` 省略时,`/v1/accounts` 保持固定域名语义;`/v1/accounts/wildcard` 会自动使用默认或随机子域。
- 固定 `subdomain` 后,不同本地前缀可以复用同一个真实子域,只要最终邮箱地址不冲突即可。
- 只有兼容旧脚本或高级排障时,才需要显式传 `wildcardRuleId` / `subdomainLabel`。普通脚本继续按 `domain + subdomain` 理解即可。
- 创建成功后,后续 `POST /v1/token`、`GET /v1/messages`、`GET /v1/messages/{id}` 都必须使用接口返回的最终 `address`。
- 如果通过 owner 侧接入自定义域名,默认 DNS 主流程只需要 `TXT + MX`;启用泛子域名时再补一条 `wildcard MX`,默认不需要额外 `CNAME`。
认证: API Key / Bearer JWT / YYDS Mail 官方网页入口
请求体
{
"localPart": "my-prefix",
"domain": "your-domain.com",
"subdomain": "optional"
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"address": "my-prefix@example.com",
"mode": "fixed",
"domain": "example.com",
"subdomain": "",
"token": "eyJhbGciOiJIUzI1NiIs...",
"inboxType": "temp",
"source": "api",
"expiresAt": "2026-03-15T12: 00: 00Z",
"isActive": true,
"createdAt": "2026-03-14T12: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/accounts \ -X POST \ -H "X-API-Key: AC-your-key" \ -H "Content-Type: application/json" \ -d '{"localPart":"my-prefix","domain":"public.example.com"}'
普通域名示例
{
"localPart": "my-prefix",
"domain": "public.example.com"
}泛子域名自动分配示例(推荐走 /v1/accounts/wildcard)
{
"success": true,
"data": {
"mode": "wildcard",
"address": "my-prefix@a3f9c2.public.example.com",
"domain": "a3f9c2.public.example.com",
"subdomain": "a3f9c2"
}
}泛子域名默认配置示例
{
"localPart": "my-prefix"
}泛子域名固定子域示例
{
"localPart": "my-prefix",
"domain": "public.example.com",
"subdomain": "team-a"
}/v1/accounts/wildcard创建临时邮箱。既支持普通域名,也支持通过泛子域名创建真实子域邮箱。
泛子域名场景继续传 `domain`,再额外传一个可选的 `subdomain`。
认证: API Key / Bearer JWT / YYDS Mail 官方网页入口
请求体
{
"localPart": "my-prefix",
"domain": "public.example.com",
"subdomain": "optional"
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"address": "my-prefix@mail.example.com",
"mode": "wildcard",
"domain": "mail.example.com",
"subdomain": "mail",
"token": "eyJhbGciOiJIUzI1NiIs...",
"inboxType": "temp",
"source": "api",
"expiresAt": "2026-03-15T12: 00: 00Z",
"isActive": true,
"createdAt": "2026-03-14T12: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/accounts/wildcard \ -X POST \ -H "X-API-Key: AC-your-key" \ -H "Content-Type: application/json" \ -d '{"localPart":"my-prefix","domain":"public.example.com","subdomain":"team-a"}'
/v1/token认证: 临时 Token(同一邮箱)
请求体
{
"address": "k7xm2pa9bf@public.example.com"
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"address": "k7xm2pa9bf@public.example.com",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}示例
curl https://maliapi.215.im/v1/token \ -X POST \ -H "Authorization: Bearer <temp_token>" \ -H "Content-Type: application/json" \ -d '{"address":"k7xm2pa9bf@public.example.com"}'
后续继续使用最终 address 刷新 token
{
"address": "my-prefix@mail.team-a.example.com"
}/v1/accounts/me认证: 临时 Token
响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"address": "k7xm2pa9bf@public.example.com",
"inboxType": "temp",
"source": "web",
"expiresAt": "2026-03-15T12: 00: 00Z",
"isActive": true,
"messageCount": 3,
"createdAt": "2026-03-14T12: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/accounts/me \ -H "Authorization: Bearer <temp_token>"
/v1/inboxes/{id}认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 临时邮箱 ID |
响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"address": "k7xm2pa9bf@public.example.com",
"inboxType": "temp",
"source": "api",
"expiresAt": "2026-03-15T12: 00: 00Z",
"isActive": true,
"messageCount": 0,
"createdAt": "2026-03-14T12: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/inboxes/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \ -H "Authorization: Bearer <temp_token>"
/v1/accounts/{id}已废弃认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 临时邮箱 ID |
示例
curl https://maliapi.215.im/v1/accounts/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \ -H "Authorization: Bearer <temp_token>"
/v1/accounts/{id}认证: 临时 Token
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 临时邮箱 ID |
响应
204 No Content
示例
curl https://maliapi.215.im/v1/accounts/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \ -X DELETE \ -H "Authorization: Bearer <temp_token>"
消息管理
读取、管理和删除邮件消息。支持临时 Token、API Key 或 JWT 认证。
/v1/inboxes/{id}/messages认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 临时邮箱 ID |
示例
curl "https://maliapi.215.im/v1/inboxes/f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3/messages?seen=false&limit=20 class="code-string">" \ -H "Authorization: Bearer <token>"
/v1/messages认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
| limit | number | 否 | 返回消息数量上限(默认:50) |
| seen | boolean | 否 | 可选。按已读状态过滤:true 只返回已读,false 只返回未读。 |
| since | string | 否 | 可选。RFC3339 时间戳(含边界),只返回该时间之后的邮件,例如 2026-01-02T15:04:05Z。 |
| q | string | 否 | 可选。对主题和发件人(名称/地址)做大小写不敏感的子串搜索。 |
| after_id | string | 否 | 可选。游标分页:返回该邮件 ID 之后(更旧)的邮件;与响应中的 nextCursor 配合使用,优先级高于 offset。 |
响应
{
"success": true,
"data": {
"messages": [
{
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"inbox_id": "f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3",
"inboxId": "f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3",
"from": { "name": "Sender", "address": "sender@example.com" },
"to": [{ "name": "", "address": "k7xm2pa9bf@public.example.com" }],
"subject": "Welcome!",
"seen": false,
"hasAttachments": false,
"size": 1234,
"createdAt": "2026-03-14T12: 30: 00Z"
}
],
"total": 1,
"unreadCount": 1
}
}示例
curl "https://maliapi.215.im/v1/messages?address=k7xm2pa9bf@public.example.com" \ -H "Authorization: Bearer <token>"
后续查询邮件时使用创建返回的最终 address
# 创建邮箱后请保存返回值里的 address curl "https://maliapi.215.im/v1/messages?address=my-prefix@mail.team-a.example.com" \ -H "Authorization: Bearer <token>"
过滤 + 游标翻页
# 只拉未读、按关键词搜索 curl "https://maliapi.215.im/v1/messages?address=k7xm2pa9bf@public.example.com&seen=false&q=verification&limit=20 class="code-string">" \ -H "Authorization: Bearer <token>" # 用上一页返回的 nextCursor 继续翻页 curl "https://maliapi.215.im/v1/messages?address=k7xm2pa9bf@public.example.com&seen=false&after_id=<nextCursor> class="code-string">" \ -H "Authorization: Bearer <token>"
使用任一过滤参数(seen / since / q / after_id)时,响应会额外返回 nextCursor:还有更多结果时为最后一条的 ID,否则为空字符串。不带这些参数的请求响应结构与旧版完全一致。
/v1/messages/next认证: 临时 Token / API Key(写)/ Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| address | string | 否 | 限定取件邮箱(可选)。省略时在你名下全部活跃邮箱中取最旧未读。 |
| wait | number | 否 | 长轮询秒数(0-30,可选)。服务器挂起请求直到有新未读邮件或超时(超时返回 204)。 |
响应
{
"success": true,
"data": {
"message": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"from": { "name": "Example", "address": "noreply@example.com" },
"to": [{ "name": "", "address": "k7xm2pa9bf@public.example.com" }],
"subject": "Your verification code",
"text": "Your verification code is 384729.",
"html": ["<p>Your verification code is 384729.</p>"],
"seen": true,
"hasAttachments": false,
"size": 1234,
"createdAt": "2026-07-02T12: 30: 00Z",
"verificationCode": "384729"
},
"inboxAddress": "k7xm2pa9bf@public.example.com"
}
}
// 无未读邮件时(等待窗口结束后):
204 No Content示例
curl "https://maliapi.215.im/v1/messages/next?address=k7xm2pa9bf@public.example.com&wait=30 class="code-string">" \ -H "X-API-Key: AC-xxxxxx"
/v1/messages/mark-read认证: 临时 Token / API Key(写)/ Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
响应
{
"success": true,
"data": {
"mailbox": "k7xm2pa9bf@public.example.com",
"updated": 3,
"alreadySeen": 1,
"total": 4
}
}示例
curl "https://maliapi.215.im/v1/messages/mark-read?address=k7xm2pa9bf@public.example.com" \ -X POST \ -H "Authorization: Bearer <token>"
/v1/messages/{id}认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 邮件 ID |
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"from": { "name": "Sender", "address": "sender@example.com" },
"to": [{ "name": "", "address": "k7xm2pa9bf@public.example.com" }],
"subject": "Welcome!",
"text": "Hello, this is a test email. Your verification code is 384729.",
"html": ["<p>Hello, this is a test email.</p>"],
"seen": true,
"hasAttachments": true,
"size": 1234,
"createdAt": "2026-03-14T12: 30: 00Z",
"verificationCode": "384729",
"attachments": [
{
"id": "0",
"filename": "welcome.pdf",
"contentType": "application/pdf",
"size": 2048,
"downloadUrl": "/serve/mailbox/demo/message/attach/0/welcome.pdf"
}
]
}
}示例
curl "https://maliapi.215.im/v1/messages/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4?address=k7xm2pa9bf@public.example.com" \ -H "Authorization: Bearer <token>"
/v1/messages/{id}认证: 临时 Token / API Key(写)/ Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 邮件 ID |
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
请求体
{
"seen": true
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"seen": true
}
}示例
curl "https://maliapi.215.im/v1/messages/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4?address=k7xm2pa9bf@public.example.com" \ -X PATCH \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"seen":true}'
标记未读
curl "https://maliapi.215.im/v1/messages/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4?address=k7xm2pa9bf@public.example.com" \ -X PATCH \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"seen":false}'
/v1/messages/{id}认证: 临时 Token / API Key(写)/ Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 邮件 ID |
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
响应
204 No Content
示例
curl "https://maliapi.215.im/v1/messages/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4?address=k7xm2pa9bf@public.example.com" \ -X DELETE \ -H "Authorization: Bearer <token>"
/v1/sources/{id}认证: 临时 Token / API Key / Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | 邮件 ID |
| address | string | 否 | 邮箱地址(查询参数,JWT / API Key 用户必填) |
响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"data": "Return-Path: <sender@example.com>\r\nFrom: Sender <sender@example.com>\r\nTo: k7xm2pa9bf@public.example.com\r\nSubject: Welcome!\r\n..."
}
}示例
curl "https://maliapi.215.im/v1/sources/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4?address=k7xm2pa9bf@public.example.com" \ -H "Authorization: Bearer <token>"
Webhook 管理
设置 Webhook 以在事件发生时接收实时 HTTP 通知。
/v1/me/webhooks认证: Bearer Token / API Key
响应
{
"success": true,
"data": {
"webhooks": [
{
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"userId": "u_123",
"url": "https://example.com/hook",
"events": ["message.received", "message.deleted"],
"isActive": true,
"createdAt": "2026-03-14T12: 00: 00Z",
"updatedAt": "2026-03-14T12: 00: 00Z"
}
],
"total": 1
}
}示例
curl https://maliapi.215.im/v1/me/webhooks \ -H "Authorization: Bearer <token>"
/v1/me/webhooks认证: Bearer JWT
请求体
{
"url": "https://example.com/hook",
"events": ["message.received", "message.deleted"]
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"userId": "u_123",
"url": "https://example.com/hook",
"events": ["message.received", "message.deleted"],
"secret": "e3b0c44298fc1c149afbf4c8996fb924...",
"hasSecret": true,
"secretHint": "e3b0c442",
"isActive": true,
"createdAt": "2026-03-14T12: 00: 00Z",
"updatedAt": "2026-03-14T12: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/me/webhooks \ -X POST \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/hook class="code-string">","events":["message.received","message.deleted"]}'
签名校验与投递载荷
每次投递都带 HMAC-SHA256 签名。校验方法:取 X-YYDS-Timestamp 头与原始请求体,拼接为「时间戳.请求体」,用您的 Webhook 密钥计算 HMAC-SHA256,与 X-YYDS-Signature 头中 sha256= 后的十六进制值比对。建议同时拒绝时间戳过旧的请求(如超过 5 分钟)以防重放。载荷仅包含邮件头信息,不含正文 — 请通过 GET /v1/messages/{id}?address=<mailbox> 获取完整内容。
POST <your-webhook-url>
Content-Type: application/json
X-YYDS-Event: message.received
X-YYDS-Delivery: <delivery-id>
X-YYDS-Timestamp: <unix-seconds>
X-YYDS-Signature: sha256=HEX(HMAC-SHA256(secret, "<timestamp>.<raw-body>"))
{
"event": "message.received",
"deliveryId": "…",
"timestamp": "2026-07-02T10:30:00Z",
"source": "local",
"messageId": "…",
"mailbox": "you@example.com",
"from": { "name": "Alice", "address": "alice@example.com" },
"to": [{ "name": "", "address": "you@example.com" }],
"subject": "Hello",
"date": "2026-07-02T10:29:58Z",
"size": 2048,
"hasAttachments": false
}外部邮箱事件:绑定的外部 IMAP 账号同步到新邮件时,同样触发 message.received(载荷中 source="external",并附带 accountId 与 accountEmail;本地邮件为 source="local")。防风暴聚合:单账号单轮同步新邮件超过 50 封时,不再逐封投递,而是发送一条 messages.bulk_received 聚合事件(含 count),订阅了 messages.bulk_received 或 message.received 的 Webhook 均会收到。
{
"event": "messages.bulk_received",
"deliveryId": "…",
"timestamp": "2026-07-02T10:30:00Z",
"source": "external",
"mailbox": "you@gmail.com",
"count": 120,
"accountId": "ea_123",
"accountEmail": "you@gmail.com"
}投递失败按 1 分钟 / 5 分钟 / 30 分钟 / 2 小时 / 6 小时 指数退避重试,共 6 次。连续失败 20 次后 Webhook 将被自动停用(修复端点后可在控制台重新启用)。端点需在 10 秒内返回 2xx;重定向不会被跟随。
/v1/me/webhooks/{id}认证: Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | Webhook ID |
响应
204 No Content
示例
curl https://maliapi.215.im/v1/me/webhooks/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \ -X DELETE \ -H "Authorization: Bearer <token>"
/v1/me/webhooks/{id}认证: Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | Webhook ID |
请求体
{
"url": "https://new-endpoint.example.com/hook",
"events": ["message.received", "message.deleted"],
"isActive": false
}响应
{
"success": true,
"data": {
"id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"userId": "u_123",
"url": "https://new-endpoint.example.com/hook",
"events": ["message.received", "message.deleted"],
"isActive": false,
"createdAt": "2026-03-14T12: 00: 00Z",
"updatedAt": "2026-03-21T08: 00: 00Z"
}
}示例
curl https://maliapi.215.im/v1/me/webhooks/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \ -X PATCH \ -H "Authorization: Bearer <jwt>" \ -H "Content-Type: application/json" \ -d '{"url":"https://new-endpoint.example.com/hook class="code-string">","isActive":false}'
/v1/me/webhooks/{id}/test认证: Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | Webhook ID |
响应
{
"success": true,
"data": {
"success": true,
"statusCode": 200,
"latencyMs": 156
}
}示例
curl https://maliapi.215.im/v1/me/webhooks/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/test \ -X POST \ -H "Authorization: Bearer <jwt>"
/v1/me/webhooks/{id}/rotate-secret认证: Bearer JWT
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | Webhook ID |
响应
{
"success": true,
"data": {
"webhookId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"secret": "e3b0c44298fc1c149afbf4c8996fb924...",
"secretHint": "e3b0c442"
}
}示例
curl https://maliapi.215.im/v1/me/webhooks/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/rotate-secret \ -X POST \ -H "Authorization: Bearer <jwt>"
/v1/me/webhooks/{id}/deliveries认证: Bearer Token / API Key
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | string | 是 | Webhook ID |
| limit | number | 否 | 返回条数(默认 20,最大 50) |
| offset | number | 否 | 偏移量(默认 0) |
响应
{
"success": true,
"data": {
"deliveries": [
{
"id": "d1e2f3…",
"webhookId": "a1b2c3d4…",
"event": "message.received",
"status": "failed",
"statusCode": 500,
"error": "endpoint returned HTTP 500",
"durationMs": 312,
"attemptCount": 2,
"maxAttempts": 6,
"nextAttemptAt": "2026-07-02T11: 05: 00Z",
"createdAt": "2026-07-02T10: 30: 00Z",
"attempts": [
{ "attemptNo": 1, "statusCode": 500, "durationMs": 280, "createdAt": "2026-07-02T10: 30: 01Z" },
{ "attemptNo": 2, "statusCode": 500, "durationMs": 312, "createdAt": "2026-07-02T10: 31: 02Z" }
]
}
],
"total": 1
}
}示例
curl "https://maliapi.215.im/v1/me/webhooks/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/deliveries?limit=50" \ -H "Authorization: Bearer <token>"
AI / LLM 集成
提供 llms.txt 端点,让 AI 助手(如 ChatGPT、Claude)快速理解公开集成面与认证方式,帮助您编写接入代码。
/v1/llms.txt响应
# yyds Mail API
> Public integration summary for developers and AI assistants.
> Base URL: https://maliapi.215.im/v1
## Public Scope
- Quick Start
- Temporary Email
- Messages
- Webhooks
- Error Handling
Additional public query endpoints:
- GET /v1/domains
- GET /v1/plans
- GET /v1/pricing
- GET /v1/domain-reward/config
- GET /v1/stats
## Authentication
- Bearer JWT: Authorization: Bearer <access_token>
- API Key: X-API-Key: AC-xxx
- Temp Token: Authorization: Bearer <temp_token>
- Temp tokens only work for temporary inbox flows
- Anonymous temp inbox creation is only available through the official homepage bridge
- Signed-in domain onboarding, wildcard rule management, and DNS automation are owner features inside the dashboard
- DNS automation is optional. Without a service connection, custom-domain onboarding remains manual TXT + MX setup
## Temporary Email
POST /v1/accounts — Create a temporary inbox
POST /v1/token — Refresh the temp token for the same active inbox
GET /v1/accounts/me — Get current temp inbox profile
GET /v1/inboxes/{id} — Get inbox detail by ID (canonical)
GET /v1/accounts/{id} — DEPRECATED alias of GET /v1/inboxes/{id}
DELETE /v1/accounts/{id} — Deactivate a temporary inbox
## Messages
GET /v1/inboxes/{id}/messages — List messages by inbox ID (canonical)
GET /v1/messages?address=xxx — List messages for an inbox (address-keyed)
GET /v1/messages/next?address=xxx&wait=30 — Take the next unread message (auto marks read; response includes verificationCode; 204 when none)
POST /v1/messages/mark-read?address=xxx — Mark mailbox messages as read
GET /v1/messages/{id}?address=xxx — Get message detail (includes verificationCode when an OTP-style code is detected)
PATCH /v1/messages/{id}?address=xxx — Update message state
DELETE /v1/messages/{id}?address=xxx — Delete a message
GET /v1/sources/{id}?address=xxx — Get raw message source
## Webhooks
GET /v1/me/webhooks — List webhook subscriptions
POST /v1/me/webhooks — Create a webhook (signing secret shown once)
PATCH /v1/me/webhooks/{id} — Update a webhook
DELETE /v1/me/webhooks/{id} — Delete a webhook
POST /v1/me/webhooks/{id}/test — Send a signed test event
POST /v1/me/webhooks/{id}/rotate-secret — Rotate the webhook signing secret
GET /v1/me/webhooks/{id}/deliveries — List recent deliveries
## Error Handling
All errors follow the same envelope:
{ "success": false, "error": "...", "errorCode": "..." }
...示例
curl https://maliapi.215.im/v1/llms.txt
如何使用
将 llms.txt 的 URL 提供给任意 AI 助手,它就能理解公开集成面并帮助您编写接入代码。
# ChatGPT / Claude / other AI assistants
# Just point the AI to:
https://maliapi.215.im/v1/llms.txt
# The AI can then understand the public integration surface
# and help you write integration code.OpenAPI 规范
完整的机器可读 API 契约(OpenAPI 3.1)——覆盖全部公开端点、认证方式与统一响应信封,并与服务端代码保持同步。
https://maliapi.215.im/v1/openapi.yaml将规范 URL 直接导入 Postman(Import → Link)或任意兼容 OpenAPI 的工具,即可获得一套可直接调用的请求集合。
错误处理
所有错误响应遵循统一格式:
{
"success": false,
"error": "Invalid or expired token",
"errorCode": "token_invalid_or_expired"
}HTTP 状态码
| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 201 | 创建成功 |
| 400 | 请求错误 — 参数无效 |
| 401 | 未授权 — 令牌缺失或无效 |
| 403 | 禁止访问 — 权限不足 |
| 404 | 未找到 |
| 429 | 请求过多 — 已触发限流 |
| 500 | 服务器内部错误 |
速率限制
API 请求在三个层级进行限流:基于 IP、基于用户和基于 API Key。触发限流时,API 返回 429 状态码,并在 Retry-After 响应头中指示重试时间。
限流响应头
所有经过限流的请求(包括成功响应和 429)都会携带以下响应头,便于客户端预判和退避:
| 响应头 | 说明 |
|---|---|
| X-RateLimit-Limit | 当前令牌桶容量(burst),即桶满时可瞬时发出的最大请求数。 |
| X-RateLimit-Remaining | 本次请求后桶内剩余的可用请求数。 |
| X-RateLimit-Reset | 令牌桶完全恢复到满容量的 Unix 秒时间戳。 |
| Retry-After | 仅 429 响应携带:建议等待的秒数。 |
各认证方式默认配额
| 认证方式 | 限流桶 | 默认配额 |
|---|---|---|
| 匿名 / 临时邮箱 Token | 按 IP | 5 req/s · burst 20 |
| 登录用户(JWT) | 按用户(Web 请求享 3 倍速率) | 套餐 RPS × 3 · burst = RPS × 10 × 3 |
| API Key | 按用户 + 热点路径分桶 | 套餐 RPS · burst = RPS × 10;另受套餐每日/每周/每月调用量限制 |
套餐 RPS 见价格页各档位(例如 Free 10 req/s、Basic 30 req/s、Pro 60 req/s);已验证自定义域名可获得额外速率加成。匿名默认 5 req/s、burst 20。所有数值可由运营端配置调整,以响应头中的实时值为准。
配额与限速:额度用尽(quota_exhausted)
429 有两种语义:普通限速(按 Retry-After 退避后重试即可)和额度用尽。当套餐的每日/每周/每月调用额度用尽且没有调用包余量时,后续 API 请求会被立即拒绝,返回 errorCode: quota_exhausted,并附带 resetAt(额度重置时间,北京时间)与 upgrade 购买链接。在 resetAt 之前重试只会持续收到 429 —— 升级套餐或购买调用包可立即恢复。网页控制台不受熔断影响,随时可登录购买。
HTTP/1.1 429 Too Many Requests Retry-After: 28800 X-RateLimit-Reset: 1751731200 { "success": false, "error": "API 调用额度已用尽。购买调用包或升级套餐可立即恢复,也可等待额度自动重置。", "errorCode": "quota_exhausted", "resetAt": "2026-07-06T00: 00: 00+08: 00", "upgrade": { "pricing": "https://vip.215.im/pricing", "callPacks": "https://vip.215.im/balance" } }
正确的退避方式:先看 errorCode 区分两种 429,额度用尽时停止重试。
resp = requests.get(url, headers=headers)
if resp.status_code == 429:
body = resp.json()
if body.get("errorCode") == "quota_exhausted":
# 额度用尽:重试无意义,等 resetAt 或购买调用包立即恢复
raise QuotaExhausted(body["resetAt"], body["upgrade"])
# 普通限速:按 Retry-After 退避后重试
time.sleep(int(resp.headers.get("Retry-After", "1")))