> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meoo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 云服务 API

云服务 API 用于开通项目云服务、获取连接凭证、管理云数据库、对象存储、云函数、认证方式和 Secret。首次接入可先阅读 [云服务使用指南](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGkoG9YwHZn269gqV6EDybno)，再按本文查询具体参数。

适用分支：`openapi-0915`。核对日期：2026-09-10。

基础地址：`https://meoo.com/open/v1`

## 调用约定

所有接口使用 `Authorization: Bearer <token>`。系统集成使用具备相应 Scope 的团队成员短期 Token，或已授权的 OAuth Access Token；用户 API Key 可用于个人测试和临时调试。凭证所属租户必须能够访问目标项目，并且当前用户具备对应的项目操作权限。

`project_id` 是项目公开 URL ID，不是数据库主键；长度为 1～50，只能包含英文字母、数字、`_` 和 `-`。本文示例先设置：

```text theme={null}
export BASE_URL='https://meoo.com/open/v1'
export PROJECT_ID='your-project-url-id'
export ACCESS_TOKEN='replace-with-authorized-bearer-token'
```

示例 Token 和项目 ID 均为占位符。执行写操作前请替换为自己的测试项目及数据。所有成功响应均为 HTTP `200`，直接返回本文所示 JSON 对象，不包含 `success`、`result` 或 `data` 外层包装。请求体必须为 JSON 对象，不接受未列出的字段；客户端应容忍响应未来新增字段。

除数据库 SQL 结果中的时间值外，资源响应中的时间戳均为 Unix 毫秒，可能为 `null`。对象大小、存储桶大小上限、估算行数以字符串返回，避免整数精度损失。

## 接口与权限一览

下表路径均以 `/projects/{project_id}` 为前缀。不同 Scope 不会自动相互包含，例如 `cloud.read` 不能代替 `cloud.credentials.read`，`cloud.database.read` 不能执行 SQL。

| 方法     | 路径                                             | 用途            | Scope                      |
| :----- | :--------------------------------------------- | :------------ | :------------------------- |
| POST   | `/cloud`                                       | 开通云服务         | `cloud.write`              |
| GET    | `/cloud/credentials`                           | 获取客户端及服务端凭证   | `cloud.credentials.read`   |
| GET    | `/cloud/database/status`                       | 查询数据库状态       | `cloud.database.read`      |
| GET    | `/cloud/database/tables`                       | 查询表结构         | `cloud.database.read`      |
| POST   | `/cloud/database/queries`                      | 执行 SQL        | `cloud.database.write`     |
| GET    | `/cloud/storage/buckets`                       | 查询存储桶         | `cloud.storage.read`       |
| GET    | `/cloud/storage/buckets/{bucket_name}/objects` | 分页查询对象        | `cloud.storage.read`       |
| PUT    | `/cloud/storage/buckets/{bucket_name}/objects` | 上传或覆盖对象       | `cloud.storage.write`      |
| DELETE | `/cloud/storage/buckets/{bucket_name}/objects` | 删除对象          | `cloud.storage.write`      |
| GET    | `/cloud/functions`                             | 查询云函数         | `cloud.function.read`      |
| PUT    | `/cloud/functions/{function_name}`             | 部署或更新云函数      | `cloud.function.write`     |
| DELETE | `/cloud/functions/{function_name}`             | 删除云函数         | `cloud.function.write`     |
| GET    | `/cloud/functions/{function_name}/logs`        | 查询函数日志        | `cloud.function.logs.read` |
| PUT    | `/cloud/auth/providers`                        | 启用认证方式        | `cloud.write`              |
| GET    | `/cloud/secrets`                               | 查询 Secret 元数据 | `cloud.secret.read`        |
| PUT    | `/cloud/secrets/{secret_name}`                 | 创建或覆盖 Secret  | `cloud.secret.write`       |
| DELETE | `/cloud/secrets/{secret_name}`                 | 删除 Secret     | `cloud.secret.write`       |

项目 API Key 只能访问绑定的项目；当前项目 API Key 默认权限集合不包含 `cloud.credentials.read` 和 `cloud.storage.write`，这两类操作请使用已授予对应权限的成员短期 Token、OAuth Access Token 或用户 API Key。

## 开通与连接

### 开通项目云服务

```text theme={null}
POST /projects/{project_id}/cloud
```

所需权限：`cloud.write`。

该接口同步完成云服务开通。首次开通成功后返回 `status: "ready"`、`created: true`；已经开通的项目返回 `created: false`。无需获取任务 ID 或等待异步开通任务。

请求体可以省略，也可以传 `{}`。

| 字段            | 类型     | 必填 | 说明                           |
| :------------ | :----- | :- | :--------------------------- |
| `description` | string | 否  | 云服务描述；非空，最多 200 个字符，首尾空白会被去除 |

```text theme={null}
curl --fail-with-body --silent --show-error --request POST \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"description":"活动报名项目云服务"}'
```

响应字段：

| 字段           | 类型              | 说明                         |
| :----------- | :-------------- | :------------------------- |
| `status`     | string          | 成功时固定为 `ready`             |
| `created`    | boolean         | 本次是否新开通云服务                 |
| `public_url` | string / null   | 实例公网根地址，可选；获取完整连接信息请调用凭证接口 |
| `warnings`   | array of string | 可选，附属步骤的非致命警告；存在时应检查内容     |

首次开通响应示例：

```text theme={null}
{
  "status": "ready",
  "created": true,
  "public_url": "https://your-instance.example",
  "warnings": []
}
```

已开通时可能仅返回：

```text theme={null}
{
  "status": "ready",
  "created": false
}
```

此接口开通云资源；应用的业务表、RLS 策略、客户端代码和 SDK 依赖仍需按实际业务配置。权益或数量额度不足时返回 `403 quota_exceeded`。

### 获取云服务凭证

```text theme={null}
GET /projects/{project_id}/cloud/credentials
```

所需权限：`cloud.credentials.read`。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/credentials" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段            | 类型            | 说明                                |
| :------------ | :------------ | :-------------------------------- |
| `url`         | string / null | 实例公网根地址；未取得可用地址时为 `null`          |
| `anon_key`    | string        | 客户端匿名密钥；客户端数据访问仍应受 RLS 策略约束       |
| `service_key` | string        | Service Role Key，可绕过 RLS，仅用于可信服务端 |

```text theme={null}
{
  "url": "https://your-instance.example",
  "anon_key": "<anon-key>",
  "service_key": "<service-role-key>"
}
```

这是高权限管理接口，响应禁止缓存（`Cache-Control: private, no-store`）。应在可信服务端调用，只将应用需要的 `url` 和 `anon_key` 配置给客户端。`service_key` 不得发送到浏览器、写入前端环境变量或日志。项目尚未开通时返回 `409 cloud_not_enabled`。

## 云数据库

### 查询数据库状态

```text theme={null}
GET /projects/{project_id}/cloud/database/status
```

所需权限：`cloud.database.read`。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/database/status" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

响应只有一个 `status` 字段：

| 值             | 说明               |
| :------------ | :--------------- |
| `not_enabled` | 项目尚未开通云数据库       |
| `ready`       | 项目已存在当前有效的云数据库实例 |

```text theme={null}
{"status":"ready"}
```

未开通是正常状态，HTTP 仍为 `200`；该接口不返回实例 ID、数据库地址或凭证。需要开通时调用 `POST /projects/{project_id}/cloud`。

### 查询数据表结构

```text theme={null}
GET /projects/{project_id}/cloud/database/tables
```

所需权限：`cloud.database.read`。

返回 `public` Schema 中的数据表、字段和行级安全（RLS）信息，不接受自定义 Schema 参数。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/database/tables" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段                        | 类型            | 说明          |
| :------------------------ | :------------ | :---------- |
| `tables`                  | array         | 数据表列表       |
| `tables[].schema`         | string        | Schema 名称   |
| `tables[].name`           | string        | 表名          |
| `tables[].rls_enabled`    | boolean       | 是否启用 RLS    |
| `tables[].rls_forced`     | boolean       | 是否强制应用 RLS  |
| `tables[].estimated_rows` | string        | 估算行数，不是精确计数 |
| `tables[].comment`        | string / null | 表说明         |
| `tables[].columns`        | array         | 字段列表        |

`columns[]` 字段：

| 字段              | 类型              | 说明            |
| :-------------- | :-------------- | :------------ |
| `name`          | string          | 字段名           |
| `data_type`     | string          | 数据类型          |
| `format`        | string          | 格式化后的类型信息     |
| `nullable`      | boolean         | 是否允许 `null`   |
| `updatable`     | boolean         | 是否可更新         |
| `unique`        | boolean         | 是否具有唯一约束      |
| `default_value` | string / null   | 默认值表达式        |
| `enums`         | array of string | 枚举值；非枚举字段为空数组 |
| `comment`       | string / null   | 字段说明          |

```text theme={null}
{
  "tables": [
    {
      "schema": "public",
      "name": "registrations",
      "rls_enabled": true,
      "rls_forced": false,
      "estimated_rows": "1280",
      "comment": "活动报名记录",
      "columns": [
        {
          "name": "id",
          "data_type": "uuid",
          "format": "uuid",
          "nullable": false,
          "updatable": true,
          "unique": true,
          "default_value": "gen_random_uuid()",
          "enums": [],
          "comment": "报名记录 ID"
        }
      ]
    }
  ]
}
```

### 执行 SQL

```text theme={null}
POST /projects/{project_id}/cloud/database/queries
```

所需权限：`cloud.database.write`，包括只执行 `SELECT` 的请求。

该接口接受查询、数据变更、表结构变更、权限变更、事务控制及多条 SQL，适用于可信服务端的数据库管理。应用用户的数据读写应通过应用客户端及对应 RLS 策略处理。

| 字段      | 类型     | 必填 | 说明                                      |
| :------ | :----- | :- | :-------------------------------------- |
| `query` | string | 是  | SQL 字符串；去除首尾空白后不能为空，最多 65536 个 UTF-8 字节 |

无需业务表即可执行的连通性示例：

```text theme={null}
curl --fail-with-body --silent --show-error --request POST \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/database/queries" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"query":"select 1 as ok"}'
```

```text theme={null}
{
  "rows": [{"ok":1}],
  "columns": ["ok"],
  "row_count": 1,
  "truncated": false
}
```

| 字段          | 类型              | 说明                                             |
| :---------- | :-------------- | :--------------------------------------------- |
| `rows`      | array of object | 返回数据行，最多 100 行                                 |
| `columns`   | array of string | 结果列名                                           |
| `row_count` | integer         | SQL 返回的总结果行数；数据库提供受影响行数时也用于 DML，可能大于 `rows` 数量 |
| `truncated` | boolean         | `rows` 是否因 100 行上限被截断                          |

响应最多 100 行且不超过 1 MiB。`truncated: true` 只表示返回的数据不完整，SQL 仍可能已经完整执行。响应超过 1 MiB 时返回 `413 response_too_large`，请通过列选择、过滤条件和 SQL 分页缩小结果。

同一请求中的多条 SQL 按同一事务执行，任一 SQL 语句失败时整次请求回滚。响应大小限制、请求超时和网络中断不等于数据库回滚；对有副作用的 SQL，先查询实际数据或表结构确认结果，再决定是否重试。

SQL 结果值的映射：

| PostgreSQL 类型                 | JSON 表示                                 |
| :---------------------------- | :-------------------------------------- |
| `bigint`、`numeric`            | 十进制字符串，避免精度损失                           |
| `bytea`                       | Base64 字符串                              |
| `json`、`jsonb`、boolean、`null` | 保持相应 JSON 类型                            |
| 日期、时间、UUID                    | 字符串；日期时间保留 PostgreSQL 文本格式，不转换为 Unix 毫秒 |

SQL 语法、对象名称或约束错误返回 `400 invalid_query`，需要修改 SQL 后重试；云服务故障返回 `502 upstream_error`。

## 对象存储

支持查询存储桶、分页查询对象、上传/覆盖对象及批量删除对象。本文接口不提供独立的存储桶创建、对象下载或下载链接签发操作；应用文件访问可使用云服务客户端的 Storage 能力。

所有 `bucket_name` 长度为 1～100，以英文字母或数字开头，其余字符允许英文字母、数字、`.`、`_`、`-`。请使用真实存在的桶名，不要直接照搬示例 `uploads`。

### 查询存储桶

```text theme={null}
GET /projects/{project_id}/cloud/storage/buckets
```

所需权限：`cloud.storage.read`。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/storage/buckets" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段                             | 类型                     | 说明                        |
| :----------------------------- | :--------------------- | :------------------------ |
| `buckets`                      | array                  | 存储桶列表                     |
| `buckets[].name`               | string                 | 存储桶名称                     |
| `buckets[].public`             | boolean                | 是否允许公开读取                  |
| `buckets[].file_size_limit`    | string / null          | 单文件大小限制，单位字节；未设置时为 `null` |
| `buckets[].allowed_mime_types` | array of string / null | 允许的 MIME 类型；未设置时为 `null`  |
| `buckets[].created_at`         | integer / null         | 创建时间，Unix 毫秒              |
| `buckets[].updated_at`         | integer / null         | 更新时间，Unix 毫秒              |

```text theme={null}
{
  "buckets": [
    {
      "name": "uploads",
      "public": false,
      "file_size_limit": "10485760",
      "allowed_mime_types": ["image/png", "image/jpeg"],
      "created_at": 1786410000000,
      "updated_at": 1786410000000
    }
  ]
}
```

桶本身的大小上限不改变下述 Open API 上传接口的单文件 5 MiB 上限。

### 查询对象列表

```text theme={null}
GET /projects/{project_id}/cloud/storage/buckets/{bucket_name}/objects
```

所需权限：`cloud.storage.read`。

Query 参数：

| 参数           | 类型      | 必填 | 说明                                             |
| :----------- | :------ | :- | :--------------------------------------------- |
| `prefix`     | string  | 否  | 路径前缀，最多 1024 个 UTF-8 字节，不允许控制字符；默认空字符串，从桶根目录查询 |
| `page_size`  | integer | 否  | 默认 20；`0` 使用默认值，超过 100 按 100 处理；不接受负数          |
| `page_token` | string  | 否  | 上一页响应中的 `next_page_token`，最多 2048 个字符          |

按对象名升序分页。翻页时保持相同的 `bucket_name` 和 `prefix`，原样传回令牌，不要自行解析或修改。

```text theme={null}
curl --fail-with-body --silent --show-error --get \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/storage/buckets/uploads/objects" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --data-urlencode 'prefix=images/' \
  --data-urlencode 'page_size=20'
```

| 字段                | 类型     | 说明                  |
| :---------------- | :----- | :------------------ |
| `bucket_name`     | string | 存储桶名称               |
| `prefix`          | string | 本次查询的路径前缀           |
| `objects`         | array  | 对象与目录前缀列表           |
| `next_page_token` | string | 可选；有下一页时返回，没有下一页时省略 |

`objects[]` 字段：

| 字段                 | 类型             | 说明                     |
| :----------------- | :------------- | :--------------------- |
| `name`             | string         | 对象名或目录前缀               |
| `type`             | string         | `object` 或 `prefix`    |
| `size`             | string / null  | 对象大小，单位字节；目录前缀为 `null` |
| `mime_type`        | string / null  | MIME 类型                |
| `cache_control`    | string / null  | Cache-Control 配置       |
| `etag`             | string / null  | 对象 ETag                |
| `created_at`       | integer / null | 创建时间，Unix 毫秒           |
| `updated_at`       | integer / null | 更新时间，Unix 毫秒           |
| `last_accessed_at` | integer / null | 最近访问时间，Unix 毫秒         |

```text theme={null}
{
  "bucket_name": "uploads",
  "prefix": "images/",
  "objects": [
    {
      "name": "banner.png",
      "type": "object",
      "size": "245760",
      "mime_type": "image/png",
      "cache_control": "max-age=3600",
      "etag": "d41d8cd98f00b204e9800998ecf8427e",
      "created_at": 1786410000000,
      "updated_at": 1786410000000,
      "last_accessed_at": 1786413600000
    }
  ]
}
```

### 上传或覆盖对象

```text theme={null}
PUT /projects/{project_id}/cloud/storage/buckets/{bucket_name}/objects
```

所需权限：`cloud.storage.write`。

| 字段               | 类型      | 必填 | 说明                                                    |
| :--------------- | :------ | :- | :---------------------------------------------------- |
| `path`           | string  | 是  | 桶内完整对象路径，最多 1024 个 UTF-8 字节；首尾空白会被去除                  |
| `content_base64` | string  | 是  | 文件内容的标准 Base64，无换行和 data URL 前缀；解码后为 1 字节～5 MiB       |
| `content_type`   | string  | 是  | MIME 类型，例如 `text/plain`、`image/png`；不附带 `charset` 等参数 |
| `cache_control`  | string  | 否  | 1～200 个字符的缓存设置，不允许换行                                  |
| `upsert`         | boolean | 否  | 默认 `true`，允许覆盖相同路径；传 `false` 表示不覆盖                    |

`path` 不能以 `/` 开头或结尾，不能含空路径段、`.`、`..` 或控制字符。文件写入还需满足目标桶的文件类型和大小配置。

以下内容 `aGVsbG8=` 解码后为 `hello`，目标桶需允许 `text/plain`：

```text theme={null}
curl --fail-with-body --silent --show-error --request PUT \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/storage/buckets/uploads/objects" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "path":"docs/hello.txt",
    "content_base64":"aGVsbG8=",
    "content_type":"text/plain",
    "cache_control":"max-age=3600",
    "upsert":false
  }'
```

| 字段             | 类型      | 说明          |
| :------------- | :------ | :---------- |
| `bucket_name`  | string  | 目标存储桶       |
| `path`         | string  | 对象路径        |
| `size`         | string  | 解码后的文件字节数   |
| `content_type` | string  | 文件 MIME 类型  |
| `uploaded`     | boolean | 成功时为 `true` |

```text theme={null}
{
  "bucket_name": "uploads",
  "path": "docs/hello.txt",
  "size": "5",
  "content_type": "text/plain",
  "uploaded": true
}
```

超过 5 MiB 时返回 `413 artifact_too_large`。此接口返回上传结果，不返回下载 URL。

### 删除对象

```text theme={null}
DELETE /projects/{project_id}/cloud/storage/buckets/{bucket_name}/objects
```

所需权限：`cloud.storage.write`。

| 字段      | 类型              | 必填 | 说明                                       |
| :------ | :-------------- | :- | :--------------------------------------- |
| `paths` | array of string | 是  | 1～100 个桶内完整对象路径；重复路径去重；每项格式与上传 `path` 一致 |

```text theme={null}
curl --fail-with-body --silent --show-error --request DELETE \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/storage/buckets/uploads/objects" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"paths":["docs/hello.txt"]}'
```

| 字段            | 类型              | 说明          |
| :------------ | :-------------- | :---------- |
| `bucket_name` | string          | 目标存储桶       |
| `deleted`     | array of string | 本次删除返回的对象路径 |

```text theme={null}
{
  "bucket_name": "uploads",
  "deleted": ["docs/hello.txt"]
}
```

## 云函数

云函数运行在 Deno Edge Runtime，函数包的根目录应包含 `index.ts`。`function_name` 长度为 1～64，必须以英文字母开头，其余字符仅允许英文字母、数字、`_` 和 `-`。

### 查询云函数

```text theme={null}
GET /projects/{project_id}/cloud/functions
```

所需权限：`cloud.function.read`。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/functions" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

返回 `functions` 数组，每个函数包含：

| 字段           | 类型             | 说明                                |
| :----------- | :------------- | :-------------------------------- |
| `name`       | string         | 函数名称                              |
| `status`     | string         | 函数当前状态，例如 `ACTIVE`；客户端不要假定只存在一种状态 |
| `version`    | integer        | 当前版本号                             |
| `verify_jwt` | boolean        | 调用时是否启用 JWT 校验                    |
| `created_at` | integer / null | 创建时间，Unix 毫秒                      |
| `updated_at` | integer / null | 更新时间，Unix 毫秒                      |

```text theme={null}
{
  "functions": [
    {
      "name": "hello-world",
      "status": "ACTIVE",
      "version": 1,
      "verify_jwt": true,
      "created_at": 1786410000000,
      "updated_at": 1786410000000
    }
  ]
}
```

### 部署或更新云函数

```text theme={null}
PUT /projects/{project_id}/cloud/functions/{function_name}
```

所需权限：`cloud.function.write`。

函数不存在时创建，名称已存在时更新。部署成功同步返回 HTTP `200` 和函数信息；此接口不返回异步任务 ID。新建函数受云函数数量权益和项目额度约束。

| 字段               | 类型      | 必填 | 说明                                                                      |
| :--------------- | :------ | :- | :---------------------------------------------------------------------- |
| `archive_base64` | string  | 是  | ZIP 文件的标准 Base64，无换行和 data URL 前缀；解码后为 1 字节～10 MiB；ZIP 根目录包含 `index.ts` |
| `verify_jwt`     | boolean | 否  | 默认 `true`；需要登录用户身份时保持开启。`false` 适用于明确允许匿名调用的函数                          |

准备 `hello-world/index.ts`，在该目录内部打包，避免 ZIP 多套一层目录。以下示例依赖 `zip` 和 Python 3，仅用于生成请求体：

```text theme={null}
(cd hello-world && zip -r ../hello-world.zip .)

python3 - <<'PY' > function-request.json
import base64
import json
from pathlib import Path

archive = Path('hello-world.zip').read_bytes()
print(json.dumps({
    'archive_base64': base64.b64encode(archive).decode('ascii'),
    'verify_jwt': True,
}))
PY

curl --fail-with-body --silent --show-error --request PUT \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/functions/hello-world" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary @function-request.json
```

响应中的 `function` 与上文函数列表的单项结构一致：

```text theme={null}
{
  "function": {
    "name": "hello-world",
    "status": "ACTIVE",
    "version": 1,
    "verify_jwt": true,
    "created_at": 1786410000000,
    "updated_at": 1786410000000
  }
}
```

函数代码修改后需要重新部署，源码上传本身不会更新已部署函数。ZIP 超过 10 MiB 时返回 `413 artifact_too_large`；新增数量超限返回 `403 quota_exceeded`；数量权益暂时无法确认时可返回 `503 service_unavailable`。

函数的业务调用通过云实例的 `/functions/v1/{function_name}` 入口完成，具体代码与应用登录态处理见 [云服务使用指南](https://alidocs.dingtalk.com/i/nodes/KGZLxjv9VGkoG9YwHZn269gqV6EDybno)。不要将 Open API 管理令牌作为应用用户 JWT 使用。

### 删除云函数

```text theme={null}
DELETE /projects/{project_id}/cloud/functions/{function_name}
```

所需权限：`cloud.function.write`。

```text theme={null}
curl --fail-with-body --silent --show-error --request DELETE \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/functions/hello-world" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段        | 类型      | 说明          |
| :-------- | :------ | :---------- |
| `name`    | string  | 函数名称        |
| `deleted` | boolean | 成功时为 `true` |

```text theme={null}
{"name":"hello-world","deleted":true}
```

### 查询云函数日志

```text theme={null}
GET /projects/{project_id}/cloud/functions/{function_name}/logs
```

所需权限：`cloud.function.logs.read`。

Query 参数：

| 参数           | 类型      | 必填 | 说明                                        |
| :----------- | :------ | :- | :---------------------------------------- |
| `start_time` | integer | 否  | 查询起点，包含，Unix 毫秒时间戳；默认是 `end_time` 前 15 分钟 |
| `end_time`   | integer | 否  | 查询终点，不包含，Unix 毫秒时间戳；默认当前时间                |
| `limit`      | integer | 否  | 返回条数，默认 100，范围 1～500                      |

`start_time` 必须小于 `end_time`，单次范围不超过 1 小时。不传时间即查询最近 15 分钟。该接口不返回分页令牌；需要更长历史时按时间窗口分次查询。

```text theme={null}
curl --fail-with-body --silent --show-error --get \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/functions/hello-world/logs" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --data-urlencode 'limit=100'
```

| 字段                    | 类型             | 说明                     |
| :-------------------- | :------------- | :--------------------- |
| `function_name`       | string         | 函数名称                   |
| `start_time`          | integer        | 实际查询起点，Unix 毫秒         |
| `end_time`            | integer        | 实际查询终点，Unix 毫秒         |
| `total`               | integer        | 查询返回的匹配日志总数            |
| `returned`            | integer        | 本次 `entries` 条数，最多 500 |
| `entries`             | array          | 日志列表                   |
| `entries[].timestamp` | integer / null | 日志时间，Unix 毫秒           |
| `entries[].level`     | string / null  | 日志级别                   |
| `entries[].message`   | string         | 日志内容                   |
| `entries[].stack`     | string         | 可选，存在时返回错误堆栈           |

```text theme={null}
{
  "function_name": "hello-world",
  "start_time": 1786410000000,
  "end_time": 1786410900000,
  "total": 1,
  "returned": 1,
  "entries": [
    {
      "timestamp": 1786410123000,
      "level": "info",
      "message": "[hello-world] request completed"
    }
  ]
}
```

## 用户认证方式

### 启用认证方式

```text theme={null}
PUT /projects/{project_id}/cloud/auth/providers
```

所需权限：`cloud.write`。

| 字段          | 类型              | 必填 | 说明                                     |
| :---------- | :-------------- | :- | :------------------------------------- |
| `providers` | array of string | 是  | 非空数组，支持 `password`、`email`、`sms`；重复项去重 |

该接口启用指定认证方式，不提供禁用参数；不应通过省略某一方式或传空数组来关闭已启用方式。启用配置后，登录、注册、验证码等应用流程仍需在业务代码中接入。

```text theme={null}
curl --fail-with-body --silent --show-error --request PUT \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/auth/providers" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"providers":["password","email"]}'
```

响应 `providers` 只列出本次请求的认证方式：

| 字段                     | 类型      | 说明                         |
| :--------------------- | :------ | :------------------------- |
| `providers`            | array   | 本次启用结果                     |
| `providers[].provider` | string  | `password`、`email` 或 `sms` |
| `providers[].enabled`  | boolean | 成功时为 `true`                |

```text theme={null}
{
  "providers": [
    {"provider":"password","enabled":true},
    {"provider":"email","enabled":true}
  ]
}
```

## Secret

Secret 适合保存云函数调用外部服务所需的密钥，函数中可通过 `Deno.env.get('SECRET_NAME')` 读取。接口只返回名称和更新结果，不返回 Secret 明文。

`secret_name` 长度为 1～128，必须以英文字母或 `_` 开头，只能包含英文字母、数字和 `_`。

### 查询 Secret 列表

```text theme={null}
GET /projects/{project_id}/cloud/secrets
```

所需权限：`cloud.secret.read`。

```text theme={null}
curl --fail-with-body --silent --show-error \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/secrets" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段                     | 类型             | 说明           |
| :--------------------- | :------------- | :----------- |
| `secrets`              | array          | Secret 元数据列表 |
| `secrets[].name`       | string         | Secret 名称    |
| `secrets[].updated_at` | integer / null | 更新时间，Unix 毫秒 |

```text theme={null}
{
  "secrets": [
    {"name":"EMAIL_API_KEY","updated_at":1786410000000}
  ]
}
```

### 创建或覆盖 Secret

```text theme={null}
PUT /projects/{project_id}/cloud/secrets/{secret_name}
```

所需权限：`cloud.secret.write`。

| 字段      | 类型     | 必填 | 说明                                |
| :------ | :----- | :- | :-------------------------------- |
| `value` | string | 是  | 非空字符串，最多 65536 个 UTF-8 字节；不是字符数上限 |

```text theme={null}
curl --fail-with-body --silent --show-error --request PUT \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/secrets/EMAIL_API_KEY" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"value":"replace-with-secret-value"}'
```

示例使用占位值；真实集成应从服务端密钥配置生成请求，避免将明文复制到共享脚本、命令历史或日志。

| 字段        | 类型      | 说明                      |
| :-------- | :------ | :---------------------- |
| `name`    | string  | Secret 名称               |
| `updated` | boolean | 成功时为 `true`；不回显 `value` |

```text theme={null}
{"name":"EMAIL_API_KEY","updated":true}
```

### 删除 Secret

```text theme={null}
DELETE /projects/{project_id}/cloud/secrets/{secret_name}
```

所需权限：`cloud.secret.write`。

```text theme={null}
curl --fail-with-body --silent --show-error --request DELETE \
  --url "$BASE_URL/projects/$PROJECT_ID/cloud/secrets/EMAIL_API_KEY" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

| 字段        | 类型      | 说明          |
| :-------- | :------ | :---------- |
| `name`    | string  | Secret 名称   |
| `deleted` | boolean | 成功时为 `true` |

```text theme={null}
{"name":"EMAIL_API_KEY","deleted":true}
```

Secret 不存在时返回 `404 not_found`。

## 限流与错误处理

所有调用都受凭证/应用及当前用户维度的限流约束。部分操作另有项目维度限制，同类写入共享下表对应的限制：

| 操作               | 项目维度限制    |
| :--------------- | :-------- |
| 开通云服务            | 5 秒内 1 次  |
| 获取凭证             | 60 秒内 5 次 |
| 上传、删除 Storage 对象 | 1 秒内共 2 次 |
| 部署、删除云函数         | 2 秒内共 1 次 |
| 启用认证方式           | 2 秒内 1 次  |
| 创建、覆盖、删除 Secret  | 1 秒内共 1 次 |

遇到 `429` 时按 `Retry-After` 响应头等待，不要立即密集重试。其他限流维度也可能先达到上限。

错误使用 `application/problem+json`：

```text theme={null}
{
  "type": "about:blank",
  "title": "Conflict",
  "status": 409,
  "detail": "当前项目尚未启用云服务",
  "code": "cloud_not_enabled",
  "trace_id": "<trace-id>"
}
```

| 字段         | 说明                |
| :--------- | :---------------- |
| `type`     | 固定为 `about:blank` |
| `title`    | HTTP 错误类别         |
| `status`   | HTTP 状态码          |
| `detail`   | 本次错误说明            |
| `code`     | 可供程序判断的错误码        |
| `trace_id` | 请求跟踪 ID；排查问题时提供此值 |

响应头也提供 `X-Meoo-Trace-Id`。常见错误如下：

| HTTP 状态 | 常见 code                   | 说明与处理                              |
| :------ | :------------------------ | :--------------------------------- |
| 400     | `invalid_request`         | 请求体、名称、路径、Base64、时间范围等不符合要求；修正参数   |
| 400     | `invalid_query`           | SQL 语法、对象或约束错误；修正 SQL              |
| 400     | `invalid_page_token`      | 分页令牌无效，或与桶名、前缀不匹配；重新从首页查询          |
| 401     | `invalid_token`           | Bearer 凭证缺失、无效或过期；重新获取有效凭证         |
| 403     | `insufficient_scope`      | 缺少接口要求的 Scope                      |
| 403     | `forbidden`               | 凭证绑定的项目边界等限制不允许本次操作                |
| 403     | `quota_exceeded`          | 开通云服务或新增函数的权益/数量额度不足               |
| 404     | `not_found`               | 资源不存在，或当前用户无权限访问；检查项目、桶、函数或 Secret |
| 409     | `cloud_not_enabled`       | 尚未启用对应云服务；先开通项目云服务                 |
| 413     | `artifact_too_large`      | 上传对象超过 5 MiB，或函数 ZIP 超过 10 MiB     |
| 413     | `response_too_large`      | SQL 返回结果超过 1 MiB；缩小结果范围            |
| 429     | `temporarily_unavailable` | 触发限流；按 `Retry-After` 等待            |
| 502     | `upstream_error`          | 云服务暂不可用；写操作先核查实际执行结果再决定重试          |
| 503     | `service_unavailable`     | 新增云函数的数量权益暂时无法确认；稍后重试              |

项目冻结、封禁或其他不可操作状态还可能返回相应项目错误码。客户端应按 `code` 处理已知情况，并以 HTTP 状态码处理未来新增的错误码。
