OpenRouter 入门与概览

OpenRouter 入门与概览

批处理

4 分钟阅读

批处理 API 快速开始

提交并检索异步推理请求批次

批处理 API 让你一次提交大量推理请求,并异步获取结果。它适合不需要立即响应的工作,并使用 24 小时完成窗口,这样你无需自行管理每一次调用。

批处理 API 支持多种 OpenRouter API 形态,包括 Chat Completions(聊天补全)、Responses 和 Anthropic Messages。你以内联 JSON requests 数组提交请求。无需上传 JSONL 文件;OpenRouter 会在内部处理 JSONL 持久化。

批处理结果是异步可用的。提交成功会返回 202 Accepted,且 status: "validating",这表示请求已持久化并进入验证队列,并不表示每条请求都已完成。


限制

批处理 API 目前仅支持文本。在 /v1/chat/completions/v1/responses/v1/messages 上,携带图像、音频、视频或文件内容部分的请求会在验证阶段被拒绝,包括 Responses 的 input_imageinput_file 部分,以及 Anthropic 的 imagedocument 块。在 /v1/chat/completions 上,通过 modalitiesaudioimage_config 请求非文本输出同样会被拒绝。对于嵌入(embeddings),input 必须是字符串或 Token 数组。

请将多模态请求发送到同步 API。


定价

批处理请求通常按模型标准每 Token 定价的 50% 计费,与 OpenAIAnthropic 提供的批处理折扣一致。对于已完成的批次,usage.cost 报告的是 OpenRouter 收取的金额;对于经自带密钥(BYOK)路由的批次,这只是 OpenRouter 的 BYOK 手续费,因为服务提供商侧的推理费用由服务提供商直接收取。

非 Token 定价组成部分不会统一打折;例如,网络搜索调用按标准费率计费,提示词缓存费率因模型而异,因此各模型页面上显示的定价才是最终依据。


提交批次

使用以下方式提交批次:

端点
POST https://openrouter.ai/api/beta/batches

请求体有三个必填的顶层字段:

字段说明
endpoint批次中每条请求使用的 API 形态。可选 /v1/chat/completions/v1/responses/v1/messages/v1/embeddings
modelOpenRouter 模型 slug,例如 openai/gpt-4o。此批次级模型会应用到每条请求。
requests非空的 { custom_id, body } 项数组。custom_id 在批次内必须唯一,body 遵循所选 endpoint 的形态。

请在 JSON 请求体中先序列化 endpointmodel,再序列化 requests。API 会流式解析请求,以便在不缓冲的情况下接受非常大的 requests 数组;如果 requests 出现在最前面,则会返回 400。本页所有示例都已使用此顺序。

批次级 model 会应用到每条请求。请求体可以省略 model 以继承批次级值。如果请求体自行设置了 model,它必须与批次级 model 一致,否则提交会被拒绝。

在 Google 模型上,批次中的每条请求必须请求相同的 response_format:要么全部省略,要么全部使用 json_object,要么全部使用带相同 schema 的 json_schema。Google 的批处理服务会为整个批次推导一个输出 schema,因此不一致的请求会在那里失败。不一致的批次会在验证时失败,并指出第一个冲突的请求,因此请按每种 response_format 和每种 schema 分别发送批次。

import json
import requests

response = requests.post(
  url="https://openrouter.ai/api/beta/batches",
  headers={
    "Authorization": "Bearer <OPENROUTER_API_KEY>",
    "Content-Type": "application/json",
  },
  data=json.dumps({
    "endpoint": "/v1/chat/completions",
    "model": "openai/gpt-4o",
    "requests": [
      {
        "custom_id": "req-0001",
        "body": {
          "messages": [
            {
              "role": "user",
              "content": "用一句话概括 OpenRouter。"
            }
          ]
        }
      }
    ]
  })
)

print(response.json())

响应是一个批次对象,带有可用于查询进度的 ID:

202 Accepted
{
  "id": "batch_123",
  "object": "batch",
  "endpoint": "/v1/chat/completions",
  "model": "openai/gpt-4o",
  "completion_window": "24h",
  "status": "validating",
  "created_at": 1782097200,
  "finalized_at": null,
  "request_counts": {
    "total": 1,
    "completed": 0,
    "failed": 0
  },
  "usage": null,
  "results": null,
  "error": null
}

唯一支持的完成窗口是 24h


轮询结果

使用批次 ID 检索当前状态:

端点
GET https://openrouter.ai/api/beta/batches/:id

例如:

Shell
curl https://openrouter.ai/api/beta/batches/batch_123 \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

状态通常会按以下顺序推进:

状态推进
validating → in_progress → finalizing → completed

其他可能的状态包括 failedexpiredcancellingcancelled。终态为 completedfailedexpiredcancelled。请轮询直到批次到达终态。

request_counts 包含请求总数以及已完成或失败的数量:

request_counts
{
  "total": 100,
  "completed": 98,
  "failed": 2
}

当批次正在进行中,或已失败、过期或被取消时,resultsnull。批次完成后,results 会作为数组内联返回在同一响应中。没有单独的结果下载端点。

每条结果通过 custom_id 映射回输入。每条结果恰好填充 responseerror 其中之一:

结果项
{
  "id": "batch_req_123",
  "custom_id": "req-0001",
  "response": {
    "status_code": 200,
    "request_id": "request_123",
    "body": {
      "id": "gen-batch-1782097200-a1b2c3d4e5f6a7b8c9d0",
      "object": "chat.completion",
      "created": 1782097200,
      "model": "openai/gpt-4o",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "OpenRouter 通过一个 API 接入众多 AI 模型。"
          },
          "finish_reason": "stop"
        }
      ]
    }
  },
  "error": null
}

已完成批次的响应如下所示:

已完成的批次
{
  "id": "batch_123",
  "object": "batch",
  "endpoint": "/v1/chat/completions",
  "model": "openai/gpt-4o",
  "completion_window": "24h",
  "status": "completed",
  "created_at": 1782097200,
  "finalized_at": 1782100800,
  "request_counts": {
    "total": 1,
    "completed": 1,
    "failed": 0
  },
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 40,
    "total_tokens": 60,
    "cost": 0.000225,
    "is_byok": false
  },
  "results": [
    {
      "id": "batch_req_123",
      "custom_id": "req-0001",
      "response": {
        "status_code": 200,
        "request_id": "request_123",
        "body": {
          "id": "gen-batch-1782097200-a1b2c3d4e5f6a7b8c9d0",
          "object": "chat.completion",
          "created": 1782097200,
          "model": "openai/gpt-4o",
          "choices": [
            {
              "index": 0,
              "message": {
                "role": "assistant",
                "content": "OpenRouter 通过一个 API 接入众多 AI 模型。"
              },
              "finish_reason": "stop"
            }
          ]
        }
      },
      "error": null
    }
  ],
  "error": null
}

报告问题

每条已完成结果的 response.body.id 就是该请求的 OpenRouter 生成 ID(例如 gen-batch-...)。要标记一次不佳的生成,请复制该 ID,并通过 报告反馈 使用 按生成 ID 流程提交。

生成级反馈适用于 /v1/chat/completions/v1/responses/v1/messages 这些接口形态。你也可以在我们的 Discord 中分享反馈或报告问题。


使用不同的 API 形态

设置顶层 endpoint,以选择批次中每个 body 使用的请求形态。支持的形态:

  • Chat Completions:/v1/chat/completions
  • Responses:/v1/responses
  • Anthropic Messages:/v1/messages

例如,Anthropic Messages 批次使用 /v1/messages,并把 Messages 形态的请求放在每项的 body 中:

Anthropic Messages 批次
{
  "endpoint": "/v1/messages",
  "model": "anthropic/claude-3.5-sonnet",
  "requests": [
    {
      "custom_id": "req-1",
      "body": {
        "max_tokens": 32,
        "messages": [
          {
            "role": "user",
            "content": "打个招呼。"
          }
        ]
      }
    }
  ]
}

同一批次中的所有请求使用相同的顶层 endpoint。要混合 API 形态,请提交单独的批次。


嵌入(Embeddings)

嵌入功能正在支持它的服务提供商上逐步推出。

将顶层 endpoint 设为 /v1/embeddings,并把嵌入请求放在每项的 body 中。每个 body 接受一个 input(字符串、字符串数组、Token 数组,或 Token 数组的数组)。批处理 API 不支持多模态输入、input_typeprovider 偏好。如需这些功能,请使用同步 API。

input 可以是单个字符串或字符串数组。当它是数组时,该请求会在一次调用中嵌入其中的每个字符串:

嵌入批次
{
  "endpoint": "/v1/embeddings",
  "model": "openai/text-embedding-3-small",
  "requests": [
    {
      "custom_id": "emb-0001",
      "body": {
        "input": [
          "The quick brown fox jumped over the lazy dog.",
          "Pack my box with five dozen liquor jugs."
        ]
      }
    },
    {
      "custom_id": "emb-0002",
      "body": {
        "input": "The quick brown fox jumped over the lazy dog."
      }
    }
  ]
}

轮询结果的方式与其他批次相同(GET https://openrouter.ai/api/beta/batches/:id)。这些项是已完成批次对象的 results 数组中的条目(完整示例如上);每项的 body 中携带标准嵌入响应,并且每个 custom_id 对应一条结果。若请求的 input 是字符串数组,则 data 中会按 index 顺序为每个字符串返回一个嵌入对象;单字符串请求恰好返回一条:

嵌入结果
[
  {
    "id": "batch_req_emb_1",
    "custom_id": "emb-0001",
    "response": {
      "status_code": 200,
      "request_id": "request_456",
      "body": {
        "object": "list",
        "data": [
          {
            "object": "embedding",
            "embedding": [0.0023064255, -0.009327292, 0.015797347],
            "index": 0
          },
          {
            "object": "embedding",
            "embedding": [-0.012282, 0.0034567, -0.0089123],
            "index": 1
          }
        ],
        "model": "openai/text-embedding-3-small",
        "usage": {
          "prompt_tokens": 18,
          "total_tokens": 18
        }
      }
    },
    "error": null
  },
  {
    "id": "batch_req_emb_2",
    "custom_id": "emb-0002",
    "response": {
      "status_code": 200,
      "request_id": "request_789",
      "body": {
        "object": "list",
        "data": [
          {
            "object": "embedding",
            "embedding": [0.0023064255, -0.009327292, 0.015797347],
            "index": 0
          }
        ],
        "model": "openai/text-embedding-3-small",
        "usage": {
          "prompt_tokens": 8,
          "total_tokens": 8
        }
      }
    },
    "error": null
  }
]

批处理输入和结果会作为 JSONL 工件存储在 Google Cloud Storage 中,并在创建 30 天后自动删除,与上游批处理的保留窗口一致。请在 30 天保留窗口结束前下载你需要的任何结果。