Pika API 的文档是一个索引加两份文件:机器可读的 llms.txt,以及 dev.pika.art/llms/... 下每个操作各自的规范文档,另外还有一份 OpenAPI 3.1 描述文件放在 dev.pika.art/openapi.json

Pika API 官方文档在哪里

llms.txt 开头那句同时写给人和智能体:Do not infer endpoint paths, request fields, enum values, pricing, or model support from a model name or from prior knowledge. 接着它排定了取信顺序。

  1. 目录记录 GET /catalog/apis/{api_id}?expand=inputs,用来查 current availability, request fields, required inputs, enum values, and pricing metadata
  2. 该操作的 llms/... 规范文档,用来看 the exact submit endpoint, request and response examples, polling behavior, uploads, and errors
  3. llms.txt 自己只 for discovery and routing, not as a substitute for the selected operation's specification

三份文件不是互为备份,而是各管一段。目录记录里的 input_schema 是机器可校验的那份,报价与枚举值都以它为准;规范文档补的是人读的部分,包括提交响应长什么样、轮询等什么、上传怎么走、报错怎么分。两者混着用最常见的坑,是照着规范文档里的散文示例写字段名,而目录里那个字段已经换了名。

有一条裁决规则高于其余:If a prose example conflicts with the catalog input_schema, follow the catalog schema. 路径写法也由目录定死——Send the slashes in api_id literally

三跳:提交、轮询、取回

三跳请求流程图:先提交任务,再轮询任务直到状态进入终态,然后取回媒体地址

媒体类操作都是异步的,官方把流程写成三次调用:Submit: POST https://api.dev.pika.art/v1/media/{vendor}/{model}/{function},然后 Poll: GET https://api.dev.pika.art/v1/media/jobs/{request_id} until status is completed or failed,完成的任务 carries its download URL in output

# 第 1 跳——提交。body 属于具体操作,先读它的规范文档。
curl -s -X POST "https://api.dev.pika.art/v1/media/pika/pika-2.5/image-to-video" \
  -H "X-API-Key: ${PIKA_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"resolution": "1080p", "duration_s": 5, "image": "https://example.com/frame.png"}'

# 第 2 跳——拿响应里的 id 轮询,直到状态进入终态。
curl -s "https://api.dev.pika.art/v1/media/jobs/${JOB_ID}" \
  -H "X-API-Key: ${PIKA_API_KEY}"

# 第 3 跳——读取最终地址。任务完成前这个接口返回 409。
curl -s "https://api.dev.pika.art/v1/media/jobs/${JOB_ID}/content" \
  -H "X-API-Key: ${PIKA_API_KEY}"

提交响应不是结果:The submit response returns a job object containing id and status. 要留住这个 id,后面每一次调用等的都是它。Pika API 参考用 Pikaframes 的路径走了一遍同样的三跳。

中间那次轮询是绕不开的成本,官方也给了替代方案。除了任务 id,没有别的状态需要留。重试逻辑可以写得很薄:同一个 body 配固定的幂等键重发,接口会把已有任务原样返回,失败状态也一样。想省掉轮询循环,就在提交时给出回调地址,让终端事件自己推过来。

接口路径,逐字抄自文档

所有调用共用同一个基础地址 https://api.dev.pika.art

路径是三段结构,和模型名不是一回事。同一个模型可能出现在多个操作里,模型 ID 里的斜杠是字面量,不能当版本号拆开重排。目录里目前登记了 155 个可调用操作,横跨多家供应商,选操作要看函数那一段,而不是看厂牌。

媒体类接口

方法与路径作用
POST /v1/media/{vendor}/{model}/{function}提交一个生成任务。
GET /v1/media/jobs/{request_id}轮询该任务。
GET /v1/media/jobs/{request_id}/content{ "url": ... } 返回结果地址。
DELETE /v1/media/jobs/{request_id}抹掉已存媒体与提示词,返回 204

支撑类接口

方法与路径作用
GET /catalog/apis列出可调用操作,无需密钥。
POST /catalog/apis/{api_id}/quote给一份 body 定价,不执行它。
GET /billing/balance以 micro-USD 读取预付余额。

API Key 放在请求头里,还有一个 Google 用户会试错的头

官方把鉴权压成了一行:Authentication header: X-API-Key: $PIKA_API_KEY or Authorization: Bearer $PIKA_API_KEY. Google's x-goog-api-key is not accepted. 吃亏的往往是最后那句。

密钥在 dev.pika.art/keys 创建,PIKA_API_KEY 是官方推荐的环境变量名。用法规则没有留余地:Never place an API key in browser code, a URL, source control, generated output, screenshots, or chat. 浏览器应用 must call Pika through its own authenticated server route

有两个调用根本不需要密钥,正好用来确认网络连通。

# 公开目录不需要 API key。
curl -s "https://api.dev.pika.art/catalog/apis" | jq .

# OpenAPI 3.1 文件写明了接受的鉴权方式和所有可调用路径。
curl -s https://dev.pika.art/openapi.json | jq '.components.securitySchemes'

如何轮询一个媒体任务

status 有四个取值——queuedrunningcompletedfailed——只有后两个是终态。被拒的提交同样会返回任务对象,statusfailed 且带上了 error,所以一次终态判断同时覆盖成功和被拒两种情况。

import os
import time
import requests

BASE = "https://api.dev.pika.art"
HEADERS = {"X-API-Key": os.environ["PIKA_API_KEY"]}
TERMINAL = {"completed", "failed"}

def wait_for(job_id, timeout_s=900, interval_s=5):
    deadline = time.monotonic() + timeout_s
    while True:
        job = requests.get(f"{BASE}/v1/media/jobs/{job_id}", headers=HEADERS, timeout=30).json()
        if job["status"] in TERMINAL:
            return job
        if time.monotonic() > deadline:
            raise TimeoutError(f"{job_id} still {job['status']} after {timeout_s}s")
        time.sleep(interval_s)

job = wait_for(os.environ["JOB_ID"])
if job["status"] == "failed":
    # error.code 才是稳定的分支依据;error.message 会变。
    raise SystemExit(job["error"]["code"])

print(job["output"]["video"]["url"])

跑完的任务长这样:

{
  "id": "media_8f3a2c91-5b7d-4e0a-9c26-31d4f2a8e6b0",
  "status": "completed",
  "output": {
    "media_type": "video",
    "video": { "url": "https://api.dev.pika.art/v1/files/video_8f3a2c91.mp4" }
  }
}

有两个细节在生产里会咬人:结果接口 answers 409 before the job completes,提前去取是错误而不是捷径;error.codethe stable machine-readable value to branch on,而 error.message 只是会变的诊断文本。轮询间隔和总超时都得自己定。官方没有公布单个任务通常跑多久,也没给建议间隔,只有超限时才以 429 的形式返回,而且返回的是带着任务对象的失败信封。稳妥做法是给一个总超时、逐次退避,并把 Retry-After 读进来,而不是把间隔写死。

轮询不合适时可以用 webhook 顶替:在提交 body 顶层传 "webhook_url"No registration, and a rejected URL answers 400),或者在 Webhooks 页面注册一个端点。投递按 Standard Webhooks 签名,over about 55 hours 内重试,并按 webhook-id 去重;签名密钥要 by an owner or admin, never with an API key 才能读到。

不计费的接口,以及文档里的空白

目录、报价和账单读取都不计费,而 There is no free generation tier and no separate test environment。报价给出的是金额,不是承诺:余额不足、额度用完、参数组合无法定价,都不会在报价阶段暴露。把报价当预算上限,把结算金额当事实记账,中间那道差额靠日消费接口补齐,而Pika API 分层计费说明讲的是这层账怎么构成。

有三处文档一个字都没写:429 背后的速率与并发上限、完成任务的保留时长、结果地址的有效期。官方也没有发布任何厂商专用 SDK,只说 No provider-specific SDK is required。重试安全倒是写清楚了:同一个 body 配一个固定的 Idempotency-KeyNever reuse an idempotency key with a different body;失败任务会在原密钥上重放,所以重试要换新密钥。时长和分辨率是按模型封顶的,所以时长与分辨率对照表要和网页端积分模型放在一起看。

常见问题

该信哪份文档? 先看目录记录,再看操作的 llms/... 规范文档,llms.txt 只用来路由。

基础地址和鉴权头是什么? https://api.dev.pika.art,请求头用 X-API-Key: $PIKA_API_KEYAuthorization: Bearer $PIKA_API_KEYGoogle's x-goog-api-key is not accepted.

媒体任务怎么轮询? 拿提交响应里的 id 反复调用 GET /v1/media/jobs/{request_id},直到 status 变成 completedfailed,再从 output 里读地址。

必须轮询吗? 不必。提交 body 顶层带一个 "webhook_url",同一个任务对象会签名投递到你的服务器,并重试约 55 小时。

先读目录记录,把密钥放进 X-API-Key,再把提交响应当成 id 而不是结果。