豆包 API Key 怎么申请?从火山方舟拿到 key 再跑通第一次调用
数据截至 2026-08。本文只写机制,不写价格、免费额度、限流阈值和模型版本号这类下个月就可能变的数字,具体数值以火山引擎控制台当时显示的为准。
先把最短的答案放这儿:豆包模型的 API Key 不在”豆包 App”里,也不在什么独立的豆包开放平台,它在火山引擎的方舟(Ark)控制台里申请。拿到之后,这把 key 会以 Authorization: Bearer <你的key> 的形式挂在请求头上,base_url 换成方舟的地址,剩下的调用写法跟 OpenAI SDK 基本没差别。
需要先说清楚的一件事:火山引擎的文档中心是前端渲染的页面,用普通抓取工具去拉只会拿到一个 JavaScript 空壳,所以这篇文章里凡是涉及”控制台第几级菜单叫什么”的部分,我不敢按印象编,只写站内此前已经核实过的路径,并且明确标出”以你打开控制台时实际看到的为准”。反过来,凡是能拿到一手证据的部分——官方 SDK 源码、以及直接对着方舟接口打一发请求看返回什么——我会把证据一并说明白。我本人没有注册过这个账号,所以下面不会出现任何”我实测下来”的话术。
一、key 在哪拿:入口是方舟控制台,不是豆包 App
很多人第一次找豆包 API Key 会走岔,是因为”豆包”这个名字下面挂着两个完全不同的东西:一个是给普通用户用的对话产品,另一个是给开发者用的模型服务。后者的入口是火山引擎的方舟平台(产品页在 volcengine.com/product/ark,控制台在 console.volcengine.com/ark)。你在对话产品那边翻遍设置也找不到 key,因为它压根不在那儿。
按站内此前核实过的流程,拿 key 这条路上有三道坎:
第一道是实名认证。火山引擎的账号体系要求先完成实名,没实名的账号连模型都选购不了,这一步没有捷径,注册完先去把它做掉,别等代码写好了再回头折腾。
第二道是推理接入点这一层。方舟提供”自定义推理接入点”(Endpoint)的概念,在方舟控制台的在线推理里创建,创建时选好你要用哪个模型,系统会给你生成一个 ep- 开头的 ID。这一层的作用是把限流、监控、用量归因挂到接入点上——同一个账号下如果既跑对话又跑代码补全,分开建两个接入点,将来查”到底是哪个业务在烧钱”会省很多事。注意,这一层和”申请 key”是两件独立的事,不是先后必须的因果关系,但它确实是豆包和很多厂商不一样的地方,第三节会讲它对代码的实际影响。
第三道才是创建 API Key 本身,在方舟控制台的 API Key 管理页面。这一步和绝大多数平台一样:明文只显示一次,弹窗关掉就再也看不到了,当场复制进密码管理器,别只是瞄一眼觉得记住了。方舟这边的 Key 还支持比较细的权限控制,比如限定能访问的资源范围,团队协作场景值得花两分钟配上,避免一把 key 泄露就全盘失控。
二、key 拿到手,它在请求里到底怎么用
这部分不用猜,官方 Python SDK 的源码是公开的,仓库在 github.com/volcengine/volcengine-python-sdk,方舟运行时那部分在 volcenginesdkarkruntime 目录下,几个关键事实都能逐字查到。
第一,接口地址是个写死的常量。_constants.py 里定义了 BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"。所以你在 OpenAI SDK 里填 base_url 时,填到 /api/v3 为止就行,后面的 /chat/completions 由 SDK 自己拼。常见错法是把完整路径也写进 base_url,SDK 再拼一次就变成重复路径了。
第二,鉴权就是最标准的 Bearer 头。_client.py 里的 auth_headers 属性返回的就是 {"Authorization": f"Bearer {api_key}"},没有任何额外的签名步骤。这也是为什么 OpenAI 那套 SDK 能直接兼容——鉴权方式本来就一样。
第三,环境变量名是固定的三个。同一份源码里,Ark 客户端初始化时如果你不显式传参,它会去读这三个环境变量:ARK_API_KEY 取 API Key,VOLC_ACCESSKEY 和 VOLC_SECRETKEY 取 AK/SK。这意味着方舟其实给了两条鉴权路线:一条是 API Key,一条是火山引擎账号体系的 AK/SK。源码里有一句断言写得很直白——api_key 不为空,或者 ak 和 sk 同时不为空,两者必须满足其一,否则直接断言失败。
这两条路线的差别值得说一句:AK/SK 那条路在源码里会走一套 STS 临时令牌的换取逻辑,也就是先拿 AK/SK 去换一个针对具体接入点的临时凭证再调用;而 API Key 这条路,源码注释里明确写了”this api key will not be refreshed”——它不会自动刷新,是一把长期有效的静态凭证。对绝大多数只是想调个模型的场景,API Key 更省事;但也正因为它是静态的、长期的,泄露的后果比临时令牌严重得多,别硬编码进代码提交到仓库里。
写成代码,最小可跑的样子是这样(用 OpenAI 兼容路线):
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
resp = client.chat.completions.create(
model="ep-xxxxxxxxxxxx-xxxxx", # 填你控制台里那串,不要抄这个示例值
messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)
如果不想引入 openai 这个包,火山也有官方 SDK。仓库 README 里写得很清楚:pip install volcengine-python-sdk 装主包,要用方舟得装可选依赖 pip install "volcengine-python-sdk[ark]",并且用方舟服务时 Python 版本要求不低于 3.6(主包本身的门槛更低)。两条路选一条就够,项目里已经有 OpenAI 兼容层的,用第一种改动最小。
三、model 字段填什么:ep- 开头和模型名不是一回事
这是豆包和别家差别最大、也最容易让新手卡住的地方,值得单独拎出来。别家的 model 字段填的就是模型名,方舟这里填的可能是四种东西之一。
SDK 源码里有个 get_resource_type_by_endpoint_id 方法,它按前缀分派资源类型,逻辑一目了然:ep-m- 开头的识别成预置接入点(presetendpoint),ep- 开头的识别成自定义接入点(endpoint),bot- 开头的识别成 bot;都不匹配的情况下——也就是你填的是个模型 ID——代码注释写的是”for model id, default to preset endpoint”,按预置接入点处理。
这段代码能说明两件事。一是填模型 ID 确实是被支持的,不是非得先去建接入点才能调,快速验证的脚本直接填模型名就能跑。二是这两种写法在平台侧走的资源类型不同,控制台那边的限流、监控、账单归因也就跟着不同——填自定义接入点 ID,用量记在这个接入点名下;填模型 ID,就没法按接入点维度单独看这次调用的数据了。
至于 ep-m- 这类预置接入点具体是什么、怎么创建、和自定义接入点在能力上有什么区别,我只能看到源码里做了这个区分,没有拿到官方文档的正文说明,所以这里不展开——这一层的准确定义请以控制台和官方文档为准,别听任何二手转述。
实践上给三条建议:正式上线的应用优先用自定义接入点 ID,监控粒度更好用;临时脚本直接填模型 ID 省事;无论哪种,那串字符以控制台里实际显示的为准,不要照抄任何文章里的示例值,包括这一篇里的。豆包的模型迭代速度很快,半年前教程里的模型名很可能已经不是当前在售的了。
四、调不通,通常是这几种
我没有真实账号,但方舟的接口是公开可达的,用 curl 空手打一发未授权请求,服务端返回什么是能直接看到的。对 https://ark.cn-beijing.volces.com/api/v3/chat/completions 发一个不带任何鉴权头的 POST,返回 HTTP 401,body 是这样:
{"error":{"code":"AuthenticationError","message":"the API key or AK/SK in the request is missing or invalid. request id: 0217875652271...","param":"","type":"Unauthorized"}}
换成带一个格式明显不对的假 key 再打一发,同样是 401,但 message 变了:"The API key format is incorrect."。
这个差别很有用:“missing or invalid”通常意味着你的 key 根本没送到——环境变量名拼错、变量没导入当前进程、或者 SDK 初始化时 api_key 传了个 None;而**“format is incorrect”意味着东西送到了但长得不对**——大概率是复制时带了空格换行,或者把控制台上别的什么 ID 当成 key 粘过来了。先打印一下 os.getenv("ARK_API_KEY") 确认到底是哪一种,比在代码里瞎试快得多。
其余几类报错,SDK 的 _exceptions.py 把状态码和异常类的对应关系列得很整齐,照着排查就行:400 是 ArkBadRequestError(参数不对,比如超了模型的最大输入长度),401 是 ArkAuthenticationError(鉴权,见上),403 是 ArkPermissionDeniedError(key 有效但没权限碰这个资源,常见于 key 做了资源范围限制),404 是 ArkNotFoundError(报”模型不存在”最常见的原因就是 model 字段填错,参见上一节),429 是 ArkRateLimitError(限流),5xx 是 ArkInternalServerError。
有两个细节值得单独记住。
**每个异常都带 request_id。**源码里 ArkAPIError.__str__ 的实现是把 message 和 request_id 一起打出来,前面 curl 返回的报错 message 里也直接嵌了 request id。这串东西是你提工单时最有价值的信息,遇到解释不通的报错,别只截图代码,把 request_id 一起给过去。
SDK 默认已经帮你重试过了。_base_client.py 里的 _should_retry 逻辑是:服务端如果显式返回 x-should-retry 头就听它的;否则 408(请求超时)、409(锁冲突)、429(限流)以及所有 5xx 都会触发重试,重试次数取客户端的 max_retries(我查看源码时默认值是 2,具体以你装的版本为准)。这意味着你在应用层看到的那一次 429,其实底下已经重试过几轮了。别在外面再套一层激进的立即重试,那只会把限流状况推得更糟;要加也是加带退避的队列,或者把并发降下来。
五、用量和账单在哪看
这块我只写机制,不写数字——豆包的调价和额度活动节奏很快,任何文章里写死的数字都撑不过几个月。
**账单口径。**方舟是按 token 后付费的,用量和扣费明细在控制台的账单/用量页面查。这里回扣第一节说的接入点:如果你用自定义接入点 ID 调用,用量能按接入点维度拆开看;如果全都填模型 ID,那就只能看到一笔总账,出问题时定位不到是哪个业务。所以”要不要建接入点”这个问题,本质上是”将来你想不想分清楚账”。
**估算成本之前先搞懂计费形状。豆包多个模型走的是分段计费——按单次请求的输入长度落在哪个区间,决定这次请求全部 token(含输出)**走哪一档单价,而不是”超出部分单独加价”。这一点不搞清楚,拿单价在心里乘一乘算出来的月成本会偏得离谱。具体的区间边界和每档单价,站内有一篇专门算过账的可以看:豆包 API 怎么收费。
**免费额度有抵扣边界。**新用户额度不是”什么消费都能抵”,它对插件调用、知识库调用、批量推理、缓存存储费这几类的抵扣规则和在线推理不一样。规划验证方案之前先看清楚边界,别等账单出来才发现钱照扣:豆包 API 的免费额度怎么看。至于额度的具体数值和是否仍在有效期,以你注册时控制台开通管理页实际显示的条款为准,网上流传的各种”每日再送多少”的说法,没有官方一手页面确认过的一律别当预算依据。
常见坑清单
- 找错地方:豆包 API Key 在火山引擎方舟控制台申请,不在豆包对话产品的设置里。
- 没实名就开干:实名认证是硬门槛,没实名连模型都选购不了。
- key 只显示一次:弹窗关掉就是明文再见,当场存进密码管理器。
- base_url 多写了一截:填到
/api/v3为止,/chat/completions由 SDK 拼。 - model 字段抄示例值:
ep-/ep-m-/bot-/ 模型 ID 在平台侧走的资源类型不同,那串字符必须以控制台实际显示的为准。 - 401 的两种含义别混:“missing or invalid”是 key 没送到,“format is incorrect”是送到了但格式不对,排查方向完全不同。
- 报错不看 request_id:SDK 的每个异常都带它,提工单时这是最有用的一条信息。
- 在 SDK 之外再套激进重试:408/409/429/5xx 底层已经重试过,外层再叠只会让限流更严重。
- API Key 是静态长期凭证:源码注释明确写了它不会自动刷新,别硬编码进代码提交到仓库。
- 拿文章里的数字做预算:价格、额度、限流阈值、模型名都在变,以控制台当时显示的为准——包括这一篇里提到的一切。
关于本文的核实边界
有必要交代清楚哪些是查到的、哪些是没查到的。
有一手依据的:base_url 常量、Bearer 鉴权头、ARK_API_KEY / VOLC_ACCESSKEY / VOLC_SECRETKEY 三个环境变量、API Key 与 AK/SK 二选一的断言、API Key 不自动刷新的注释、ep- / ep-m- / bot- / 模型 ID 的前缀分派、异常类与状态码的对应表、重试触发条件——这些全部来自火山引擎官方 Python SDK 的公开源码;两条 401 报错原文来自对公开接口发未授权请求的返回。
没有拿到官方正文的:控制台里各级菜单的确切名称和层级、预置接入点(ep-m-)的官方定义与创建方式、API Key 权限项的完整清单。原因是火山引擎文档中心的页面是前端渲染的,普通抓取拿到的是 JS 空壳,读不到正文。这几处我按站内此前已核实的内容写了大致路径,并且都标注了以控制台实际显示为准,没有替官方下任何结论。