AI 大模型推理

  • AI 大模型推理 > API 文档 > API Key管理 >API Key限额管理

    API Key限额管理

    最近更新时间: 2026-03-24 15:43:48

    Base URL: https://api.qnaigc.com

    概述

    用于设置查询指定 APIKey 的金额限额配置(按日 / 按月 / 总限额),当用量达到限额时将触发限额拦截(返回错误)。

    认证方式

    本接口仅支持 AK/SK 签名认证:使用七牛云标准的 AK/SK 签名认证。

    Authorization: Qiniu <AccessKey>:<EncodedSign>
    

    设置 API KEY 限额

    PUT /v1/apikey/quota/:api_key

    路径参数:

    参数 类型 必填 说明
    api_key string APIKey 值

    请求头:

    名称 类型 必填 描述
    Authorization string AK/SK 签名,格式为 Qiniu <AccessKey>:<EncodedSign>
    Content-Type string application/json

    请求体:

    {
      "daily_quota": {
        "enabled": false,
        "limit": 0,
        "alert_threshold": 0
      },
      "monthly_quota": {
        "enabled": false,
        "limit": 0,
        "alert_threshold": 0
      },
      "total_quota": {
        "enabled": true,
        "limit": 100,
        "alert_threshold": 80
      }
    }
    

    字段说明:

    字段 类型 必填 说明
    daily_quota.enabled boolean 是否启用日限额
    daily_quota.limit number 日限额金额(>= 0)
    daily_quota.alert_threshold number 日限额告警阈值百分比(0~100)
    monthly_quota.enabled boolean 是否启用月限额
    monthly_quota.limit number 月限额金额(>= 0)
    monthly_quota.alert_threshold number 月限额告警阈值百分比(0~100)
    total_quota.enabled boolean 是否启用总限额(无时间范围)
    total_quota.limit number 总限额金额(>= 0)
    total_quota.alert_threshold number 总限额告警阈值百分比(0~100)

    请求示例:

    curl --location --request PUT "https://api.qnaigc.com/v1/apikey/quota/sk-xx" \
      --header "Authorization: Qiniu <AccessKey>:<EncodedSign>" \
      --header "Content-Type: application/json" \
      --data-raw '{
        "daily_quota": {"enabled": false, "limit": 0, "alert_threshold": 0},
        "monthly_quota": {"enabled": false, "limit": 0, "alert_threshold": 0},
        "total_quota": {"enabled": true, "limit": 100, "alert_threshold": 80}
      }'
    

    响应示例(200 OK)

    {
      "status": true,
      "data": {
        "daily_quota": {
        "enabled": false,
        "limit": 0,
        "alert_threshold": 0
      },
      "monthly_quota": {
        "enabled": false,
        "limit": 0,
        "alert_threshold": 0
      },
      "total_quota": {
        "enabled": true,
        "limit": 100,
        "alert_threshold": 80
      },
      "created_at": "2006-01-02 15:04:05",
      "updated_at": "2006-01-02 15:04:05"
      }
    }
    

    查询指定 API Key 的限额配置

    GET /v1/apikey/quota/:api_key

    路径参数:

    参数 类型 必填 说明
    api_key string APIKey 值

    请求头:

    名称 类型 必填 描述
    Authorization string AK/SK 签名,格式为 Qiniu <AccessKey>:<EncodedSign>

    请求示例:

    curl --location "https://api.qnaigc.com/v1/apikey/quota/sk-xx" \
      --header "Authorization: Qiniu <AccessKey>:<EncodedSign>"
    

    响应示例(200 OK)

    {
      "status": true,
      "data": {
        "daily_quota": {
          "enabled": true,
          "limit": 10,
          "alert_threshold": 80
        },
        "monthly_quota": {
          "enabled": true,
          "limit": 200,
          "alert_threshold": 80
        },
        "total_quota": {
          "enabled": false,
          "limit": 0,
          "alert_threshold": 0
        },
        "created_at": "2006-01-02 15:04:05",
        "updated_at": "2006-01-02 15:04:05"
      }
    }
    

    错误状态码

    状态码 说明
    400 请求参数错误(如 limit < 0、alert_threshold 不在 0~100)
    401 认证失败(签名无效)
    500 服务器内部错误

    注意事项

    1. api_key 支持携带 Bearer 前缀,例如:Bearer sk-xx
    2. alert_threshold 为百分比值(0~100),用于告警阈值配置;是否产生告警取决于服务端告警策略。
    3. 配额配置写入后可能存在短暂延迟才生效(0~30s)。

    AK/SK 签名算法

    概述

    七牛云 API 使用 HMAC-SHA1 签名算法进行身份验证。签名结果附加在请求头的 Authorization 字段中,格式为:

    Authorization: Qiniu <AccessKey>:<EncodedSign>
    

    签名生成步骤

    1. 生成待签名字符串

    待签名字符串由以下部分组成(每部分用换行符分隔):

    <Method> <Path>[?Query]
    Host: <Host>
    Content-Type: <Content-Type>
    [X-Qiniu-<HeaderKey>: <HeaderValue>]
    <Body>
    

    注意:

    • Method 为 HTTP 方法(如 GET、PUT),大写
    • Path 为请求路径,不包含域名和查询参数
    • Query 为查询参数(不包含开头的 ?),仅在有时才添加
    • Host 为主机名(如 api.qnaigc.com
    • Content-Type 为请求内容类型(如 application/json
    • X-Qiniu-* 为可选的自定义头,按 key 的 ASCII 顺序排列,格式化为 X-Qiniu-<Key>(每个单词首字母大写)
    • 待签名串中在 headers 部分结束后,会追加两个连续换行符 \n\n
    • Body 为请求体(仅当 Content-Type 不是 application/octet-stream 时才添加)

    2. 计算 HMAC-SHA1 签名

    使用 SecretKey 作为密钥,对待签名字符串进行 HMAC-SHA1 运算:

    const hmac = crypto.createHmac('sha1', secretKey);
    hmac.update(signingStr);
    const sign = hmac.digest();
    

    3. Base64 编码

    对签名结果进行 URL 安全的 Base64 编码(+ 替换为 -/ 替换为 _):

    function urlSafeBase64Encode(buffer) {
      return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
    }
    const encodedSign = urlSafeBase64Encode(sign);
    

    4. 生成最终凭证

    AccessKeyencodedSign 用冒号连接:

    <AccessKey>:<EncodedSign>
    

    完整示例代码(Node.js)

    下面示例演示:

    • GET /v1/apikey/quota/sk-xx 查询限额
    • PUT /v1/apikey/quota/sk-xx 设置限额(包含 JSON Body,因此签名需要包含 Content-Type 和 Body)
    const crypto = require('crypto');
    
    /**
     * URL 安全的 Base64 编码
     */
    function urlSafeBase64Encode(buffer) {
      return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
    }
    
    /**
     * 生成待签名的原始字符串
     */
    function generateSigningString(options) {
      const { method, path, query, host, contentType, headers, body } = options;
    
      let signingStr = method.toUpperCase();
      signingStr += ' ' + path;
      if (query) {
        signingStr += '?' + query;
      }
      signingStr += '\nHost: ' + host;
    
      if (contentType) {
        signingStr += '\nContent-Type: ' + contentType;
      }
    
      if (headers) {
        const sortedKeys = Object.keys(headers).sort();
        sortedKeys.forEach((key) => {
          if (key.toLowerCase().startsWith('x-qiniu-')) {
            const formattedKey = key
              .split('-')
              .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
              .join('-');
            signingStr += '\n' + formattedKey + ': ' + headers[key];
          }
        });
      }
    
      signingStr += '\n\n';
    
      if (body && contentType && contentType !== 'application/octet-stream') {
        signingStr += body;
      }
    
      return signingStr;
    }
    
    /**
     * 生成七牛云管理凭证(Access Token)
     */
    function generateAccessToken(accessKey, secretKey, requestOptions) {
      const signingStr = generateSigningString(requestOptions);
      const hmac = crypto.createHmac('sha1', secretKey);
      hmac.update(signingStr);
      const sign = hmac.digest();
      const encodedSign = urlSafeBase64Encode(sign);
      return accessKey + ':' + encodedSign;
    }
    
    async function demo() {
      const accessKey = '你的 AccessKey';
      const secretKey = '你的 SecretKey';
      const host = 'api.qnaigc.com';
    
      // 1) GET 查询限额
      const getPath = '/v1/apikey/quota/sk-xx';
      const getToken = generateAccessToken(accessKey, secretKey, {
        method: 'GET',
        path: getPath,
        host,
      });
    
      const getResp = await fetch('https://' + host + getPath, {
        headers: { Authorization: 'Qiniu ' + getToken },
      });
      console.log('GET status:', getResp.status);
      console.log(await getResp.text());
    
      // 2) PUT 设置限额
      const putPath = '/v1/apikey/quota/sk-xx';
      const putBodyObj = {
        daily_quota: { enabled: true, limit: 10, alert_threshold: 80 },
        monthly_quota: { enabled: true, limit: 200, alert_threshold: 80 },
        total_quota: { enabled: false, limit: 1000, alert_threshold: 80 },
      };
      const putBody = JSON.stringify(putBodyObj);
      const putContentType = 'application/json';
      const putToken = generateAccessToken(accessKey, secretKey, {
        method: 'PUT',
        path: putPath,
        host,
        contentType: putContentType,
        body: putBody,
      });
    
      const putResp = await fetch('https://' + host + putPath, {
        method: 'PUT',
        headers: {
          Authorization: 'Qiniu ' + putToken,
          'Content-Type': putContentType,
        },
        body: putBody,
      });
      console.log('PUT status:', putResp.status);
      console.log(await putResp.text());
    }
    
    demo().catch(console.error);
    
    以上内容是否对您有帮助?