本文へスキップ

ドキュメントキーの作成から最初のクリップまで

最初の生成に必要なすべて:キー、1つのリクエスト、ジョブ、そしてWebhook。

開発者APIは申請制です。

概要

HTTPS経由のRESTで、入出力はJSONです。すべての生成は非同期です。

ベースURL
https://api.pershot.app/v1
認証
Authorization: Bearerの後にキーを付けます。キーはsk_test_またはsk_live_で始まり、1回だけ表示されます。当社はハッシュのみを保存します。
キーの権限
各キーにはスコープがあり、スタジオで設定した場合はモデルとツールの許可リストもあります。許可リストのあるキーは、リストにあるもの(ツールを含む:画像のアップスケール、背景除去、高画質化、リップシンク、アウトペイント、画像エディター)しか使えません。それ以外には403 forbidden_modelが返されます。高画質化で1080pや4Kにするには、動画モデルと高画質化の両方が必要です。
エラーの形式
{ "error": { "code", "message", "param", "request_id" } }
ID
種類ごとの接頭辞が付きます:job_、qt_、key_、up_。
AIエージェント向け
AIエージェント向けのテキスト:入力、指定できる値、設定ごとの価格、リクエスト例seedance-2.0-fastseedance-2.0-miniqwen-image-2512-lightningqwen-image-2512qwen-image-edit-2511-lightningqwen-image-edit-2511

実際の生成はまだ公開されていません。モデルのページでメールアドレスを残していただければ、公開時に一度だけご連絡します。

クイックスタート

4つのステップと、それぞれで表示されるはずのレスポンス。

  1. 01

    キーを取得

    開発者APIは申請制です。スタジオの「APIキー」から申請してください。利用できるようになったら、そこでキーを作成してすぐにコピーします。キー全体が表示されるのは1回だけです。

    Shell
    export API_KEY="sk_test_…"
  2. 02

    リクエストを送信

    Idempotency-Keyとmax_creditsの上限を付けてショットをPOSTします。すぐに202と待機中のジョブが返り、クレジットが保留されます。

    POST /videos/generations
    curl https://api.pershot.app/v1/videos/generations \
      -H "Authorization: Bearer $API_KEY" \
      -H "Idempotency-Key: $(uuidgen)" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "seedance-2.0-fast",
        "prompt": "Perfume mist in hard side light. Slow push-in, black background, grain.",
        "duration": 5,
        "resolution": "720p",
        "aspect_ratio": "16:9",
        "generate_audio": true,
        "max_credits": 34
      }'
    表示されるはずの内容
    {
      "id": "job_01J9ZK4T8W",
      "object": "job",
      "kind": "video",
      "status": "queued",
      "money_status": "reserved",
      "queue_position": 2,
      "requested_model": "seedance-2.0-fast",
      "credits_quoted": 34,
      "credits_charged": null
    }
  3. 03

    ジョブを確認

    statusがsucceededになるまでジョブをGETします。出力のURLは署名付きで期限があるため、残したいものはダウンロードしてください。

    GET /jobs/{id}
    curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \
      -H "Authorization: Bearer $API_KEY"
    表示されるはずの内容
    {
      "id": "job_01J9ZK4T8W",
      "object": "job",
      "kind": "video",
      "status": "succeeded",
      "money_status": "settled",
      "requested_model": "seedance-2.0-fast",
      "resolved_model": "seedance-2.0-fast",
      "credits_quoted": 34,
      "credits_charged": 34,
      "outputs": [
        {
          "kind": "video",
          "url": "https://…/job_01J9ZK4T8W.mp4?sig=…",
          "width": 1280,
          "height": 720,
          "duration_s": 5
        }
      ],
      "error": null
    }
  4. 04

    Webhookを受信

    webhook_urlを渡すと、状態が変わるたびにタイムスタンプ付きの署名を添えてPOSTします。2xxで応答してください。失敗した配信はバックオフしながら再試行されます。

    POST → webhook_url
    {
      "id": "evt_01J9ZKB1QX",
      "type": "job.succeeded",
      "created_at": "2026-09-29T14:02:31Z",
      "data": {
        "job": {
          "id": "job_01J9ZK4T8W",
          "object": "job",
          "status": "succeeded",
          "money_status": "settled",
          "credits_charged": 34,
          "outputs": [
            {
              "kind": "video",
              "url": "https://…/job_01J9ZK4T8W.mp4?sig=…",
              "width": 1280,
              "height": 720,
              "duration_s": 5
            }
          ]
        }
      }
    }

エンドポイント

すべてのパスはベースURLからの相対パスです。

メソッドパス内容
GET/v1/modelsアカウントで利用できるモデル、機能、ステータス
GET/v1/pricing公開価格。ログイン時はアカウントの価格
POST/v1/quotes計画、内訳、最大課金額、有効期限(10分)
POST/v1/videos/generations動画の生成。202とジョブを返す
POST/v1/images/generations画像の生成または編集。202とジョブを返す
GET/v1/jobs/{id}ステータス、署名付きリンクとしての出力、実際の費用
GET/v1/jobsジョブの一覧(新しい順)
POST/v1/jobs/{id}/cancelキャンセルを要求。モデルがすでにジョブを受け付けていない限り、保留したクレジットは返金されます
GET/v1/balance種類別の利用可能なクレジットと保留中のクレジット
GET/v1/usage日別またはモデル別の使用状況(JSONまたはCSV)
POST/v1/uploads10 MBまでのJPEG、PNG、WebPをアップロード

見積もりと上限

すべての生成には、quote_idかmax_creditsの上限のどちらか一方が必要で、両方は指定できません。quote_idの場合はその見積もりで実行され、max_creditsの場合は価格が上限以下のときにのみ実行されます。

model: "auto"には常にmax_creditsが必要です。見積もりの有効期間は10分で、それを過ぎるとquote_expiredが返されます。

べき等性

すべての生成リクエストに、Idempotency-Keyヘッダー(表示可能なASCII文字で1〜255文字)を付けて送信してください。

24時間以内に同じキーを送ると、202ではなくHTTP 200で同じジョブが返されるため、タイムアウト後に再試行しても、2つ目のジョブが作成されたり課金されたりすることはありません。

Webhook

生成(または一括生成)でwebhook_urlを渡すと、状態の変化を受信できます。各イベントはPOSTで、JSONのボディにはid、type、created_at、dataが含まれます:ジョブのイベントではdata.job、batch.completedではdata.batchです。

イベント

  • job.queued
  • job.processing
  • job.succeeded
  • job.failed
  • job.cancelled
  • batch.completed
  • 各配信には、イベントID、タイムスタンプ、署名が付きます。ボディを信頼する前に検証してください。
  • エンドポイントが10秒以内に2xxで応答すると、配信は完了とみなされます。それ以外の場合は、1 min、5 min、30 min、2 h、6 hの後に再試行され、その後失敗として記録されます。サポートが再送することもできます。リダイレクトには従いません。
  • WebhookのURLはhttpsである必要があります。プライベート、ループバック、予約済みのアドレスのホストは、送信時にも接続時にも拒否されます。

ヘッダー

X-Signature
t=<unix>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
X-Event-Id
イベントIDで、ボディにも含まれます。再試行や再送でも同じIDが使われるため、保存しておき、処理済みのIDはスキップしてください。
署名シークレット
アカウントごとに1つのwhsec_…シークレットで、スタジオの「APIキー」にあります。HMACの鍵は、接頭辞を含むシークレット全体です。
ローテーション
ローテーション後の24時間は、古いシークレットも2つ目のv1エントリーとして署名を続けます。いずれかのv1が一致すれば配信を受け付けてください。

再シリアライズしたコピーではなく生のボディに対してHMACを計算し、定数時間で比較して、5分より古いタイムスタンプは拒否してください。

X-Signatureを検証
import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(header, rawBody, secret, toleranceSec = 300) {
  let t = null;
  const signatures = [];
  for (const item of (header ?? "").split(",")) {
    const [key, value] = item.split("=", 2);
    if (key === "t") t = Number(value);
    if (key === "v1") signatures.push(Buffer.from(value, "hex"));
  }
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
  return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}

// verifyWebhook(req.headers["x-signature"], rawBody, process.env.WEBHOOK_SECRET)
// Answer 2xx quickly, and skip an X-Event-Id you have already handled.

エラー

コードとHTTPステータスは固定です。メッセージは人が読むためのものです。

コードHTTP発生条件
invalid_request400フィールドが欠けているか、範囲外
unauthorized401キーがない、取り消されたキー、または不正な署名
insufficient_credits402残高が保留額に足りない
forbidden_model403キーの許可リストにこのモデルまたはツールが含まれていない
region_not_supported403お住まいの地域ではこのモデルが提供されていない
developer_api_closed403開発者APIが開いていないときの開発者キー。利用は申請制
member_connections_paused403ご自身のAIエージェントの接続を一時停止している間の会員ログイン(MCP、接続コード、コマンドライン)
not_found404アカウントに該当するジョブ、見積もり、アップロードがない
quote_expired409見積もりが10分より古い
price_changed409価格が上限を超えた
content_rejected422コンテンツが拒否された(課金なし)
rate_limited429このキーのリクエストが多すぎる
concurrency_limited429このアカウントで実行中のジョブが多すぎる
internal_error500当社側で問題が発生した
upstream_unavailable503モデルが利用できない(後で再試行)

モデルの結果が不確定な場合はエラーではありません:ジョブはstatusとしてunknownを返し、再送信の前に確認が行われます。

制限

リクエスト
デフォルトでキーごとに毎分60。
同時実行数
デフォルトでアカウントごとに同時3ジョブ。引き上げは申請してください。
上限
モデルの処理能力が絶対的な上限です。キーを増やしても同時実行数は増えません。

画像

POST /v1/images/generationsも同じヘッダーを受け取ります。ティアと操作に応じてモデルIDを選びます。編集モデルにはimage_urlも必要で、生成モデルはimage_urlを受け付けません。

ティア生成編集
Image Miniエコノミー · 試作qwen-image-2512-lightningqwen-image-edit-2511-lightning
Image Fastおすすめqwen-image-2512qwen-image-edit-2511

モデル別の制限

各モデルのAPIページに、値、単位、確認する側、超えた場合の挙動をまとめた完全な表があります。GET /v1/modelsは同じ制限をJSONで返します。

  • 当社が確認当社が確認し、見積もりや保留の前に400を返します。
  • 提供元が確認仕入れ先が確認します。拒否されたジョブは失敗となり、課金されません。
  • 推奨誰も確認しません。範囲内に収めると、より良い結果が得られます。
モデル主な制限完全な表
seedance-2.0-fastSeedance 2.0 Fastプロンプト2〜2,000文字 · 4〜15 s · 参照画像最大9枚 · 画像は1辺300〜6,000 px表を開く
seedance-2.0-miniSeedance 2.0 Miniプロンプト2〜2,000文字 · 4〜15 s · 参照画像最大9枚 · 画像は1辺300〜6,000 px表を開く
qwen-image-2512Qwen-Image-2512プロンプト2〜2,000文字 · 1Kまたは2K · 元画像なし表を開く
qwen-image-2512-lightningQwen-Image-2512 · Lightning 4-stepプロンプト2〜2,000文字 · 1Kまたは2K · 元画像なし表を開く
qwen-image-edit-2511Qwen-Image-Edit-2511プロンプト2〜2,000文字 · 1Kまたは2K · 元画像1枚(JPEG、PNG、WebP、最大10 MB)表を開く
qwen-image-edit-2511-lightningQwen-Image-Edit-2511 · Lightningプロンプト2〜2,000文字 · 1Kまたは2K · 元画像1枚(JPEG、PNG、WebP、最大10 MB)表を開く

アップロード

POST /v1/uploadsは、ファイルの中身から形式を判定します。アップロードリンクの有効期間は7日です。

ファイル形式最大サイズ最大の長さ
画像:開始フレーム、参照、編集の元画像JPEG, PNG, WebP10 MB–
動画:リップシンクMP450 MB60 s
音声:リップシンクMP3, WAV, M4A10 MB60 s

当社は他のホストから画像を取得しないため、そうしたリンクのサイズは仕入れ先が確認します。仕入れ先が拒否したジョブには課金されません。 同じ制限はJSONでも取得できます:GET /v1/modelsは、すべてのモデルについてlimitsオブジェクトを返します。

fal・Replicate・WaveSpeedからの移行

ベースURLとキーを変えるだけでは足りません:すべてのリクエストで、ボディのモデルID、Idempotency-Keyヘッダー、価格の上限(max_creditsまたはquote_id)も必要です。移行ガイドでは、Seedance 2.0とQwen-Imageのすべてのフィールドを対応付け、そのまま引き継げないものを一覧にしています。