API
READ
WRITE
接続方法
APIキーを確認する
右上のメニュー > 設定 > アカウント > APIキー から確認できます。
リクエストヘッダーに付与する
発行したAPIキーを Authorization ヘッダーに Bearer 形式で付与します。
ベースURLにリクエストする
以下のベースURLにエンドポイントのパスを続けてリクエストします。
APIキーはアカウントごとに1本です。キーを変更すると古いキーはすぐに使えなくなります。キーは第三者に知られないように管理してください。
ベースURL
https://stepeee.com/public-api/v1
リクエスト例
curl "https://stepeee.com/public-api/v1/projects" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
レスポンス形式・エラー
すべてのレスポンスは以下の封筒形式で返されます。
成功時
{ "data": ... }
エラー時
{ "error": { "code": "...", "message": "...", "details": { ... } } }
ステータスコード
| ステータス | 意味 |
|---|---|
| 401 | APIキーが無い・不正・失効しています |
| 403 | この操作の権限がありません(Pro プラン以上が必要な操作を Pro プラン未満のアカウントのAPIキーで呼んだ場合、チームのスタッフがチームのトークン利用履歴を取得した場合など) |
| 404 | リソースが存在しません(アクセス権限がない場合も含みます) |
| 405 | このパスでは使えない HTTP メソッドです |
| 409 | いまの状態ではこの操作ができません(自動化が動いているコンテンツの削除、同じ Idempotency-Key のリクエストを処理中など)。理由は error.code で判定してください |
| 422 | パラメータが不正、または受け付けられない内容です。validation_error のときは error.details にパラメータごとの理由が入ります |
| 429 | レート制限を超過しました |
| 500 | 予期しないエラーが発生しました |
| 503 | 処理を開始できませんでした(自動化の実行の開始に失敗した場合など)。時間をおいてやり直してください |
共通仕様
取得・操作できる範囲
APIキーの持ち主が画面で見られるものと同じ範囲を取得・操作できます。自分のプロジェクトに加え、Teamプランではチームのオーナー・管理者はチームのすべてのプロジェクト、スタッフは権限を付与されたプロジェクトを取得・操作できます。範囲外のリソースは存在しない場合と同じく404になります。
削除したデータ
削除したプロジェクト・コンセプト・タイトル・コンテンツ・素材は、完全に消えるまでの期間も含めて返しません。タイトルやコンセプトを削除した場合、その下のコンテンツも返しません。
ページング
一覧は page(1から)と per_page(1〜100、既定20)で取得する範囲を指定します。meta に総件数(total)・現在のページ(current_page)・1ページの件数(per_page)・最後のページ(last_page)が入ります。
日時
レスポンスの日時はすべて UTC の ISO 8601 形式(例: 2026-10-21T09:30:00Z)です。パラメータの from / to は、日付(2026-10-21)・日時(2026-10-21T09:30:00)・時差つきの日時(2026-10-21T18:30:00+09:00)を受け付け、時差の無いものは UTC として扱います。from はその時刻を含み、to に日付だけを指定した場合はその日の終わり(23:59:59)までを含みます。
ID
リソースは project_unique・variation_unique のような英数字の公開IDで指定します。IDは変わりません。
ファイルのURL
画像・動画・音声のURLは {url, expires_at} の形で返します。非公開のファイルは署名付きURLで、expires_at(発行から1時間)を過ぎると使えません。続けて使う場合は期限内にダウンロードして保存するか、APIを呼び直して新しいURLを取得してください。公開設定のファイルは期限の無いURLで、expires_at は null です。
値の種類
status や platform のような値は、このページに書いた英小文字の文字列で返します。今後の機能追加で値が増えることがあるため、知らない値を受け取っても処理が止まらないように実装してください。
金額
金額は通貨の最小単位の整数です(USD はセント、JPY は円)。通貨は currency に ISO 4217 の小文字(usd、jpy など)で入ります。
書き込み(Pro プラン)
GET 以外のメソッドで、タイトルの追加・コンテンツの削除・自動化の開始・投稿の承認・Webhook の登録などの操作ができます。操作は画面で同じ操作をしたときと同じ処理で、同じ規則が適用されます。書き込みは APIキーの持ち主が Pro プラン以上のときだけ使え、Pro プラン未満では403 plan_required になります。チームのメンバーは、チームのオーナーが Team プランでなくなると403 team_plan_lost になります。ただし、自動化の停止・Webhook の一覧と削除・投稿の確認の一覧はプランに関係なく使えます(プランを変えたあとも、動いている自動化や通知を止められます)。作成したときは201、それ以外は200を返します。
Idempotency-Key
通信が切れて応答を受け取れなかったときに同じ操作を安全にやり直せるよう、一部の書き込みは Idempotency-Key ヘッダーを受け付けます(受け付けるエンドポイントはパラメータの表に載せています。自動化の開始では必須です)。値には操作ごとに作った一意な文字列(UUID など。1〜255文字の表示可能な ASCII)を使ってください。同じキーで同じ内容(メソッド・パス・本文)を再送すると、操作をやり直さずに最初の応答をそのまま返し、Idempotent-Replayed: true ヘッダーを付けます。キーは APIキーの持ち主ごとに24時間有効です。同じキーで別の内容を送ると422 idempotency_key_reused、最初のリクエストがまだ処理中なら409 idempotency_request_in_progress になります。5xx の応答は保存しないので、同じキーでやり直せます。必須のエンドポイントでヘッダーが無いと422 idempotency_key_required、形式が正しくないと422 idempotency_key_invalid になります。
レート制限
APIキーごとに1分あたり120リクエストまでです(書き込みには、これに加えて下の書き込みのレート制限があります)。レスポンスヘッダーの X-RateLimit-Limit(上限)と X-RateLimit-Remaining(残り)で確認できます。超えると429が返り、Retry-After に再試行できるまでの秒数が入ります。
書き込みのレート制限
書き込み(GET 以外のメソッド)は、1分あたり120リクエストの枠に加えて、APIキーごとに1分あたり30リクエストまでです。超えると429 rate_limited が返り、Retry-After に再試行できるまでの秒数が入ります。書き込みのレスポンスヘッダーの X-RateLimit-Limit と X-RateLimit-Remaining は、2つの枠のうち残りが少ないほうの値です。
エラーコード
エラー時は error.code にエラーの種類、error.message に英語の説明が入ります。どのエンドポイントでも返りうるコードは次のとおりです。エンドポイントに固有のコード(title_limit_reached など)は、各エンドポイントのエラーの表に載せています。プログラムでは error.code で判定してください。
| コード | 意味 |
|---|---|
unauthorized | APIキーが無い・不正・失効している(401) |
forbidden | 権限が無い(403) |
plan_required | Pro プラン以上が必要な操作(403) |
team_plan_lost | チームのオーナーが Team プランでなくなったため、チームのメンバーは書き込みできない(403) |
not_found | リソースが無い、または取得できる範囲外(404) |
method_not_allowed | このパスでは使えない HTTP メソッド(405) |
conflict | いまの状態ではこの操作ができない(409) |
idempotency_request_in_progress | 同じ Idempotency-Key のリクエストがまだ処理中(409) |
validation_error | パラメータが不正(422) |
idempotency_key_required | Idempotency-Key ヘッダーが必須のエンドポイントで、ヘッダーが無い(422) |
idempotency_key_invalid | Idempotency-Key が1〜255文字の表示可能な ASCII ではない(422) |
idempotency_key_reused | 同じ Idempotency-Key を別の内容のリクエストに使った(422) |
rate_limited | レート制限を超えた(429) |
internal_error | 予期しないエラー(500) |
422 の例
{
"error": {
"code": "validation_error",
"message": "The per page field must not be greater than 100.",
"details": {
"per_page": ["The per page field must not be greater than 100."]
}
}
}
アカウント
APIキーの持ち主のアカウント情報です。プラン・トークン残高・使用量・ストレージ・支払い・紹介プログラムの状況を取得できます。
-
アカウント情報
GET /me -
サブスクリプション
GET /me/subscription -
トークン残高
GET /me/tokens -
トークン使用量
GET /me/token-usage -
ストレージ
GET /me/storage -
支払い履歴
GET /me/payments -
紹介プログラム
GET /me/referral
アカウント情報
APIキーの持ち主のプロフィール・プラン・プランごとの上限・所属チームを取得します。
| 項目 | 型 | 説明 |
|---|---|---|
user_unique |
string | ユーザーのID |
nickname |
string | null | ニックネーム |
email |
string | ログインに使うメールアドレス |
plan |
string | プラン。free / vault / plus / pro / team |
limits |
object | 今のプランの上限。null は無制限 |
limits.projects |
integer | null | 作れるプロジェクト数 |
limits.moviemode_variations_per_title |
integer | null | 動画タイトル1件あたりのコンテンツ数 |
limits.blogmode_variations_per_title |
integer | null | ブログタイトル1件あたりのコンテンツ数 |
limits.carouselmode_variations_per_title |
integer | null | カルーセルタイトル1件あたりのコンテンツ数 |
limits.postmode_variations_per_concept |
integer | null | 投稿コンセプト1件あたりのコンテンツ数 |
limits.team |
boolean | チーム機能を使えるか |
limits.script_duration_max |
integer | 動画の台本の最大の長さ(秒) |
limits.reading_time_max |
integer | ブログ記事の最大の読了時間(分) |
limits.reading_time_max_fulltext |
integer | ブログ記事を全文読み上げる場合の最大の読了時間(分) |
limits.slide_count_max |
integer | カルーセルの最大スライド枚数 |
limits.cta_enabled |
boolean | CTA(行動を促す最後のスライドなど)を使えるか |
limits.thread_enabled |
boolean | 投稿でスレッドと画像つき投稿を使えるか |
limits.schedule_title_variation_max |
integer | 予約作成で1回に指定できるタイトルとコンテンツの数 |
limits.schedule_variation_create_max |
integer | 予約作成で1回に作れるコンテンツ数 |
language |
string | null | 画面の表示言語 |
timezone |
string | 設定しているタイムゾーン(IANA 形式。例: Asia/Tokyo) |
team |
object | null | 所属しているチーム。Teamプランでない、またはチームに所属していなければ null |
team.team_unique |
string | チームのID |
team.role |
string | チームでの役割。owner(オーナー)/ admin(管理者)/ staff(スタッフ) |
created_at |
string | アカウントの作成日時 |
curl "https://stepeee.com/public-api/v1/me" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"user_unique": "aB3dE5gH7j",
"nickname": "Alice",
"email": "alice@example.com",
"plan": "pro",
"limits": {
"projects": 3,
"moviemode_variations_per_title": null,
"blogmode_variations_per_title": null,
"carouselmode_variations_per_title": null,
"postmode_variations_per_concept": null,
"team": false,
"script_duration_max": 1800,
"reading_time_max": 15,
"reading_time_max_fulltext": 4,
"slide_count_max": 20,
"cta_enabled": true,
"thread_enabled": true,
"schedule_title_variation_max": 50,
"schedule_variation_create_max": 5
},
"language": "ja",
"timezone": "Asia/Tokyo",
"team": null,
"created_at": "2026-09-01T10:20:30Z"
}
}
サブスクリプション
契約中のプランの状態・請求期間・解約予定・予約中のプラン変更を取得します。チームのメンバーは、チームのオーナーの契約内容を返します。
| 項目 | 型 | 説明 |
|---|---|---|
plan |
string | プラン。free / vault / plus / pro / team |
status |
string | 契約の状態。active(有効)/ past_due(支払いの遅延中)/ trialing(試用中)/ none(有料プランの契約なし) |
managed_by_team |
boolean | チームのオーナーの契約で利用しているか。true のとき、期間と解約の項目はオーナーの契約の値です |
current_period_start |
string | null | 今の請求期間の開始日時 |
current_period_end |
string | null | 今の請求期間の終了日時(次回の請求日時) |
cancel_at_period_end |
boolean | 今の請求期間の終わりで解約する予定か |
cancel_at |
string | null | 解約される日時 |
canceled_at |
string | null | 解約の手続きをした日時 |
scheduled_change |
object | null | 予約中のプラン変更(無ければ null) |
scheduled_change.plan |
string | 変更後のプラン |
scheduled_change.effective_at |
string | null | 変更される日時 |
curl "https://stepeee.com/public-api/v1/me/subscription" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/subscription",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/subscription", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/subscription")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/subscription"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/subscription");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"plan": "pro",
"status": "active",
"managed_by_team": false,
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"cancel_at": null,
"canceled_at": null,
"scheduled_change": {
"plan": "plus",
"effective_at": "2026-11-01T00:00:00Z"
}
}
}
トークン残高
使えるトークンの残高を取得します。チームでは、チームで共有している残高と、自分に割り当てられた利用枠を返します。
| 項目 | 型 | 説明 |
|---|---|---|
balance |
integer | 残高 |
reserved |
integer | 実行中の処理のために確保されている量 |
available |
integer | 今使える量(残高から確保中の量を引いた値) |
wallet |
string | personal(自分の残高)/ team(チームで共有している残高) |
team_quota |
object | null | チームのオーナーが設定した自分の利用枠。個人の残高を使っている場合とチームのオーナーは null |
team_quota.unlimited |
boolean | 利用枠が無制限か |
team_quota.view_only |
boolean | 閲覧のみで、トークンを使えないか |
team_quota.budget |
integer | null | 期間ごとの上限(null は無制限、0 は閲覧のみ) |
team_quota.used |
integer | 今の期間に使った量 |
team_quota.available |
integer | null | 今の期間に残っている量(無制限なら null) |
team_quota.period |
string | null | 上限の期間。day / week / month(上限が無い場合は null) |
team_quota.next_reset_at |
string | null | 使用量がリセットされる日時 |
auto_purchase.enabled |
boolean | 残高が少なくなったときの自動購入が有効か |
auto_purchase.plan |
string | null | 自動購入するトークンの種類(例: token_100)。無効なら null |
auto_purchase.threshold |
integer | 残高がこの値を下回ると自動購入します |
curl "https://stepeee.com/public-api/v1/me/tokens" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/tokens",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/tokens", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/tokens")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/tokens"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/tokens");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"balance": 90000,
"reserved": 1200,
"available": 88800,
"wallet": "team",
"team_quota": {
"unlimited": false,
"view_only": false,
"budget": 10000,
"used": 2500,
"available": 7500,
"period": "week",
"next_reset_at": "2026-10-26T00:00:00Z"
},
"auto_purchase": {
"enabled": true,
"plan": "token_100",
"threshold": 5000
}
}
}
トークン使用量
トークンの使用量と追加量を日ごと・月ごとに取得します。使用量は1日分ずつ集計され、前日分が UTC 2:45 ごろに反映されます(当日の使用量は含まれません)。購入やボーナスによる追加はすぐに反映されます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
from |
クエリ | string (YYYY-MM-DD) | 任意 | — | 期間の開始日(UTC)。省略時は to の29日前 |
to |
クエリ | string (YYYY-MM-DD) | 任意 | — | 期間の終了日(UTC、その日を含む)。省略時は今日。期間は366日まで |
group_by |
クエリ | string | 任意 | day |
集計の単位。day(日ごと)/ month(月ごと) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].period |
string | 期間。日ごとは YYYY-MM-DD、月ごとは YYYY-MM。使用も追加も無い期間は含みません |
data[].consumed |
integer | 使用量 |
data[].added |
integer | 追加量(返金の取り消しなどの減少を差し引いた値) |
data[].consumed_by_type |
object | 使用の種類ごとの内訳(text / image / video / audio など) |
data[].added_by_type |
object | 追加の種類ごとの内訳。purchase(購入)/ bonus(ボーナス)/ refund(返金)/ referral_revoke(紹介特典の取り消し。マイナス) |
meta.from |
string | 集計した期間の開始日 |
meta.to |
string | 集計した期間の終了日 |
meta.group_by |
string | 集計の単位 |
meta.total_consumed |
integer | 期間の使用量の合計 |
meta.total_added |
integer | 期間の追加量の合計 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | forbidden |
チームのトークンを使っているスタッフ(チームのトークン利用履歴はオーナーと管理者だけが取得できます) |
| 422 | validation_error |
期間が366日を超える、to が from より前、日付として読めない、group_by が day / month 以外 |
curl "https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/token-usage?from=2026-10-01&to=2026-10-20&group_by=day");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"period": "2026-10-18",
"consumed": 450,
"added": 0,
"consumed_by_type": { "image": 300, "text": 150 },
"added_by_type": {}
},
{
"period": "2026-10-20",
"consumed": 1000,
"added": 4800,
"consumed_by_type": { "video": 1000 },
"added_by_type": { "purchase": 5000, "referral_revoke": -200 }
}
],
"meta": {
"from": "2026-10-01",
"to": "2026-10-20",
"group_by": "day",
"total_consumed": 1450,
"total_added": 4800
}
}
ストレージ
ストレージの使用量と容量、ファイルの種類ごとの内訳を取得します。チームでは、チームで共有しているストレージを返します。
| 項目 | 型 | 説明 |
|---|---|---|
used_bytes |
integer | 使用量(バイト)。by_type の合計と同じ値 |
capacity_bytes |
integer | null | 容量(バイト)。null は無制限、0 はストレージなし(Freeプラン) |
by_type[].file_type |
string | null | ファイルの種類。material(素材)/ image(画像)/ video(映像)/ bgm / voice(音声)/ movie(完成動画) |
by_type[].bytes |
integer | その種類の使用量(バイト) |
by_type[].files |
integer | その種類のファイル数 |
curl "https://stepeee.com/public-api/v1/me/storage" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/storage",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/storage", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/storage")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/storage"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/storage");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"used_bytes": 734003200,
"capacity_bytes": null,
"by_type": [
{ "file_type": "image", "bytes": 52428800, "files": 120 },
{ "file_type": "movie", "bytes": 629145600, "files": 8 },
{ "file_type": "voice", "bytes": 52428800, "files": 15 }
]
}
}
支払い履歴
プランの料金やトークン購入などの支払いを新しい順に取得します。会計システムへの取り込みに使えます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
status |
クエリ | string | 任意 | — | 支払いの状態で絞り込みます(カンマ区切り)。succeeded / refunded / partially_refunded。省略時はすべて |
type |
クエリ | string | 任意 | — | 支払いの種類で絞り込みます(カンマ区切り)。値は data[].type と同じ |
from |
クエリ | string | 任意 | — | 作成日時がこの日時以降のものだけを返します |
to |
クエリ | string | 任意 | — | 作成日時がこの日時以前のものだけを返します |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].payment_unique |
string | 支払いのID |
data[].type |
string | 種類。token_first_time(初回のトークン購入)/ token_regular(トークン購入)/ subscription_vault・subscription_plus・subscription_pro・subscription_team(各プランの料金)/ smm_application・smm_contract・smm_usage(X運用代行の料金) |
data[].description |
string | 支払いの名前(英語) |
data[].status |
string | 状態。succeeded(支払い済み)/ refunded(全額返金)/ partially_refunded(一部返金) |
data[].currency |
string | 通貨(ISO 4217 の小文字) |
data[].amount_subtotal |
integer | 税抜きの金額(最小単位) |
data[].tax_amount |
integer | 税額(最小単位) |
data[].amount_total |
integer | 税込みの金額(最小単位) |
data[].line_items[] |
object | 明細。type(base_plan: プラン料金 / storage_addon: ストレージ追加 / extra_member: 追加メンバー)・quantity(数量)・amount(金額)・description(説明。無ければ null) |
data[].receipt_url |
string | null | 領収書のURL(Stripe)。発行から日数が経つと開けなくなることがあります |
data[].invoice_pdf_url |
string | null | 請求書PDFのURL(Stripe)。発行から日数が経つと開けなくなることがあります |
data[].created_at |
string | 支払い日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/payments?status=succeeded&per_page=10");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"payment_unique": "Xy12AbCd34Ef",
"type": "subscription_team",
"description": "Team Monthly",
"status": "succeeded",
"currency": "usd",
"amount_subtotal": 5000,
"tax_amount": 500,
"amount_total": 5500,
"line_items": [
{ "type": "base_plan", "quantity": 1, "amount": 4000, "description": "Team plan" },
{ "type": "extra_member", "quantity": 2, "amount": 1000, "description": null }
],
"receipt_url": "https://pay.stripe.com/receipts/...",
"invoice_pdf_url": "https://pay.stripe.com/invoice/.../pdf",
"created_at": "2026-10-01T08:00:00Z"
}
],
"meta": { "total": 1, "current_page": 1, "per_page": 10, "last_page": 1 }
}
紹介プログラム
紹介コードと、紹介の実績・報酬の状況を取得します。
| 項目 | 型 | 説明 |
|---|---|---|
code |
string | null | 紹介コード(まだ無い場合は null) |
referral_url |
string | null | 紹介用のURL(紹介コードが無い場合は null) |
is_active |
boolean | 紹介コードが有効か |
reward_type |
string | null | 報酬の受け取り方。cash(現金)/ token(トークン)。紹介コードが無い場合は null |
clicks |
integer | 紹介URLが開かれた回数 |
signups |
integer | 紹介から登録した人数 |
conversions |
integer | 紹介から有料プランを契約した人数 |
earned |
object | これまでに確定した報酬 {amount(最小単位), currency} |
earned_tokens |
integer | これまでに受け取ったトークン |
pending |
object | 確定待ちの報酬 {amount, currency} |
available |
object | 受け取りを申請できる報酬 {amount, currency} |
curl "https://stepeee.com/public-api/v1/me/referral" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/me/referral",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/me/referral", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/me/referral")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/me/referral"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/me/referral");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"code": "REFk5m2j8x9ab",
"referral_url": "https://stepeee.com?ref=REFk5m2j8x9ab",
"is_active": true,
"reward_type": "cash",
"clicks": 12,
"signups": 4,
"conversions": 2,
"earned": { "amount": 1300, "currency": "usd" },
"earned_tokens": 0,
"pending": { "amount": 300, "currency": "usd" },
"available": { "amount": 800, "currency": "usd" }
}
}
プロジェクト
プロジェクトと、その中のコンセプト・タイトルの構成を取得します。
-
プロジェクト一覧
GET /projects -
プロジェクト詳細
GET /projects/{project_unique} -
コンセプト一覧
GET /projects/{project_unique}/concepts -
コンセプト詳細
GET /projects/{project_unique}/concepts/{concept_unique}
プロジェクト一覧
取得できるプロジェクトを新しい順に取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].project_unique |
string | プロジェクトのID |
data[].project_name |
string | プロジェクト名 |
data[].description |
string | null | プロジェクトの説明 |
data[].access_level |
string | 自分の権限。owner(自分のプロジェクト)/ admin(チームのオーナー・管理者として全権限)/ edit(チームで編集権限を付与されている) |
data[].team |
object | null | チームのプロジェクトならチーム、自分だけのプロジェクトなら null |
data[].team.team_unique |
string | チームのID |
data[].is_readonly |
boolean | プランのダウングレードで上限を超え、閲覧専用になっているか(アップグレードすると解除されます) |
data[].readonly_since |
string | null | 閲覧専用になった日時 |
data[].created_at |
string | 作成日時 |
data[].updated_at |
string | 更新日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/projects" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"project_unique": "a1b2c3d4e5",
"project_name": "Sample Project",
"description": "Sample project description",
"access_level": "owner",
"team": null,
"is_readonly": false,
"readonly_since": null,
"created_at": "2026-01-10T09:00:00Z",
"updated_at": "2026-10-01T12:00:00Z"
}
],
"meta": { "total": 1, "current_page": 1, "per_page": 20, "last_page": 1 }
}
プロジェクト詳細
プロジェクト1件の詳細と、モードごとのコンセプト数・タイトル数・進捗ごとのコンテンツ数を取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
| 項目 | 型 | 説明 |
|---|---|---|
project_unique |
string | プロジェクトのID |
project_name |
string | プロジェクト名 |
description |
string | null | プロジェクトの説明 |
access_level |
string | 自分の権限。owner(自分のプロジェクト)/ admin(チームのオーナー・管理者として全権限)/ edit(チームで編集権限を付与されている) |
team |
object | null | チームのプロジェクトならチーム、自分だけのプロジェクトなら null |
team.team_unique |
string | チームのID |
is_readonly |
boolean | プランのダウングレードで上限を超え、閲覧専用になっているか(アップグレードすると解除されます) |
readonly_since |
string | null | 閲覧専用になった日時 |
created_at |
string | 作成日時 |
updated_at |
string | 更新日時 |
scope |
string | 対象地域。global(指定なし)/ region(特定の国向け) |
scope_region |
string | null | 対象の国(ISO 3166-1 alpha-2。例: JP)。global なら null |
counts.{mode}.concepts |
integer | モード(moviemode / blogmode / carouselmode / postmode)ごとのコンセプト数 |
counts.{mode}.titles |
integer | null | タイトル数(postmode はタイトルが無いため null) |
counts.{mode}.contents |
object | コンテンツ数 {total(合計), not_started(未着手), in_progress(制作中), complete(完成)} |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"project_unique": "a1b2c3d4e5",
"project_name": "Sample Project",
"description": "Sample project description",
"access_level": "owner",
"team": null,
"is_readonly": false,
"readonly_since": null,
"created_at": "2026-01-10T09:00:00Z",
"updated_at": "2026-10-01T12:00:00Z",
"scope": "region",
"scope_region": "JP",
"counts": {
"moviemode": {
"concepts": 2,
"titles": 5,
"contents": { "total": 8, "not_started": 1, "in_progress": 3, "complete": 4 }
},
"blogmode": {
"concepts": 1,
"titles": 3,
"contents": { "total": 3, "not_started": 0, "in_progress": 1, "complete": 2 }
},
"carouselmode": {
"concepts": 0,
"titles": 0,
"contents": { "total": 0, "not_started": 0, "in_progress": 0, "complete": 0 }
},
"postmode": {
"concepts": 1,
"titles": null,
"contents": { "total": 1, "not_started": 0, "in_progress": 1, "complete": 0 }
}
}
}
}
コンセプト一覧
プロジェクト内のコンセプトを、すべてのモードを横断して新しい順に取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
mode |
クエリ | string | 任意 | — | モードで絞り込みます。moviemode(動画)・blogmode(ブログ)・carouselmode(カルーセル)・postmode(投稿)をカンマ区切りで複数指定できます。省略時はすべて |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].concept_unique |
string | コンセプトのID |
data[].mode |
string | moviemode(動画)/ blogmode(ブログ)/ carouselmode(カルーセル)/ postmode(投稿) |
data[].concept_name |
string | コンセプト名 |
data[].title_count |
integer | null | タイトル数(postmode は null) |
data[].content_count |
integer | コンテンツ数 |
data[].created_at |
string | 作成日時 |
data[].updated_at |
string | 更新日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts?mode=moviemode,postmode");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"concept_unique": "pC7d2KqLx01m",
"mode": "postmode",
"concept_name": "SaaS growth tips",
"title_count": null,
"content_count": 1,
"created_at": "2026-10-02T09:00:00Z",
"updated_at": "2026-10-02T09:00:00Z"
},
{
"concept_unique": "mC4f9TnB2q",
"mode": "moviemode",
"concept_name": "Cat facts",
"title_count": 3,
"content_count": 5,
"created_at": "2026-09-20T03:00:00Z",
"updated_at": "2026-09-28T03:00:00Z"
}
],
"meta": { "total": 2, "current_page": 1, "per_page": 20, "last_page": 1 }
}
コンセプト詳細
コンセプト1件の詳細を取得します。動画・ブログ・カルーセルはタイトルの一覧、投稿(postmode)は投稿者の人物像と投稿ルールを含みます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
concept_unique |
パス | string | 必須 | — | コンセプトのID |
| 項目 | 型 | 説明 |
|---|---|---|
concept_unique / mode / concept_name / title_count / content_count / created_at / updated_at |
— | コンセプト一覧と同じ |
description |
string | null | コンセプトの説明 |
scope |
string | 対象地域。global(指定なし)/ region(特定の国向け) |
scope_region |
string | null | 対象の国(ISO 3166-1 alpha-2。例: JP)。global なら null |
default_template_unique |
string | null | 新しいコンテンツに使うセットアップテンプレート(テンプレート一覧の template_unique)。未設定、または postmode なら null |
titles |
array | null | タイトルの一覧(新しい順)。postmode は null |
titles[].title_unique |
string | タイトルのID |
titles[].title_name |
string | タイトル |
titles[].article_type |
string | null | 種類。moviemode は standard(通常)/ news(ニュース)、blogmode は standard / news / promotion(商品紹介)。carouselmode は null |
titles[].content_count |
integer | そのタイトルのコンテンツ数 |
persona |
object | null | 投稿者の人物像(postmode のみ。未作成なら null) |
persona.persona_unique |
string | 人物像のID |
persona.gender |
string | 性別。male / female / undisclosed(非公開) |
persona.generation |
string | 世代。10s / 20s / 30s / 40s / 50s / 60s_plus |
persona.region |
string | null | 文化圏の国コード |
persona.keywords |
object | 人物像のキーワード。occupation(職業)・industry(業界)・residence(住まい)・workstyle(働き方)・household(世帯)・personality(性格)は文字列、interest(関心)・expertise(専門)は文字列の配列。設定したものだけが入ります |
persona.description |
string | 人物像の文章 |
persona.casual_description |
string | null | 日常の投稿に使う人物像の文章(無ければ null) |
persona.taboos |
array | 投稿で避けること |
persona.timezone_mode |
string | タイムゾーンの決め方。auto(地域から決める。地域が無ければ投稿の言語から決める)/ specify(指定したタイムゾーン) |
persona.timezone |
string | null | 投稿のスケジュールに使うタイムゾーン(IANA 形式)。投稿ルールが未作成で決められない場合は null |
rule |
object | null | 投稿ルール(postmode のみ。未作成なら null) |
rule.rule_unique |
string | 投稿ルールのID |
rule.language |
string | 投稿の言語 |
rule.formality |
string | 話し方。very_casual(タメ口)/ casual(カジュアル)/ normal(普通)/ polite(丁寧)/ honorific(敬語) |
rule.emoji |
string | 絵文字。never(使わない)/ sometimes(たまに使う)/ often(よく使う)/ always(常に使う) |
rule.line_break |
string | 改行の多さ。none(なし)/ moderate(適度)/ frequent(多め) |
rule.post_type_share |
object | 投稿タイプの配分(%)。assertion(主張)/ knowhow(ノウハウ)/ experience(体験)/ casual(日常) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 404 | not_found |
コンセプトが無い(Concept not found.) |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/concepts/pC7d2KqLx01m");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"concept_unique": "pC7d2KqLx01m",
"mode": "postmode",
"concept_name": "SaaS growth tips",
"title_count": null,
"content_count": 1,
"created_at": "2026-10-02T09:00:00Z",
"updated_at": "2026-10-02T09:00:00Z",
"description": "Practical growth tips for SaaS founders",
"scope": "global",
"scope_region": null,
"default_template_unique": null,
"titles": null,
"persona": {
"persona_unique": "aV3kQ9mN2pRt",
"gender": "female",
"generation": "30s",
"region": "JP",
"keywords": { "occupation": "SaaS marketer", "interest": ["growth", "analytics"] },
"description": "A B2B SaaS marketer with ten years of experience...",
"casual_description": null,
"taboos": ["politics"],
"timezone_mode": "auto",
"timezone": "Asia/Tokyo",
"updated_at": "2026-10-02T09:10:00Z"
},
"rule": {
"rule_unique": "rU5tW7yZ9aBc",
"language": "ja",
"formality": "polite",
"emoji": "sometimes",
"line_break": "moderate",
"post_type_share": { "assertion": 40, "knowhow": 30, "experience": 20, "casual": 10 },
"updated_at": "2026-10-02T09:20:00Z"
}
}
}
コンテンツ
動画・ブログ・カルーセル・投稿のコンテンツを横断で取得します。詳細の package には各SNSやサイトへ投稿される内容(本文・画像・動画・キャプション)が入るため、Stepeee で作ったコンテンツを自分のシステムへ取り込めます。
-
コンテンツ一覧
GET /projects/{project_unique}/contents -
コンテンツ詳細
GET /projects/{project_unique}/contents/{variation_unique} -
投稿スケジュール
GET /projects/{project_unique}/contents/{variation_unique}/schedule
コンテンツ一覧
プロジェクト内のコンテンツ(動画・ブログ・カルーセル・投稿)を横断で取得します。進捗・掲載言語・公開の有無などで絞り込めます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
mode |
クエリ | string | 任意 | — | モードで絞り込みます。moviemode(動画)・blogmode(ブログ)・carouselmode(カルーセル)・postmode(投稿)をカンマ区切りで複数指定できます。省略時はすべて |
status |
クエリ | string | 任意 | — | 進捗で絞り込みます。not_started(未着手)/ in_progress(制作中)/ complete(完成) |
concept_unique |
クエリ | string | 任意 | — | このコンセプトのコンテンツだけを返します |
title_unique |
クエリ | string | 任意 | — | このタイトルのコンテンツだけを返します(postmode はタイトルが無いため含まれません) |
language |
クエリ | string | 任意 | — | 掲載言語で絞り込みます(例: ja、en) |
published |
クエリ | string | 任意 | — | true は投稿済みのコンテンツだけ、false はまだ投稿していないコンテンツだけを返します |
from |
クエリ | string | 任意 | — | 作成日時がこの日時以降のものだけを返します |
to |
クエリ | string | 任意 | — | 作成日時がこの日時以前のものだけを返します |
sort |
クエリ | string | 任意 | -created_at |
並び順。created_at / -created_at / updated_at / -updated_at(- は新しい順) |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].mode |
string | moviemode(動画)/ blogmode(ブログ)/ carouselmode(カルーセル)/ postmode(投稿) |
data[].variation_unique |
string | コンテンツのID |
data[].variation_no |
integer | タイトル(postmode はコンセプト)の中での番号 |
data[].title |
string | タイトル(postmode はコンセプト名) |
data[].concept |
object | 属するコンセプト {concept_unique, concept_name} |
data[].title_unique |
string | null | 属するタイトルのID(postmode は null) |
data[].language |
string | null | 掲載言語(視聴者・読者が見る言語)。未設定なら null |
data[].status |
string | 進捗。not_started(未着手)/ in_progress(制作中)/ complete(完成にしたもの) |
data[].progress.step_process |
integer | 完了した Step(0〜3) |
data[].progress.is_complete |
boolean | 完成にしたか |
data[].is_readonly |
boolean | プランのダウングレードで閲覧専用になっているか |
data[].confirmed_at |
string | null | 内容を確認済みにした日時(postmode と未確認は null) |
data[].published_platforms |
array | 投稿済み(success / partial_success)の投稿先 |
data[].created_at |
string | 作成日時 |
data[].updated_at |
string | 更新日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents?mode=blogmode&status=complete&published=false");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"mode": "blogmode",
"variation_unique": "bmA1b2C3d4E5",
"variation_no": 1,
"title": "How to start a blog",
"concept": { "concept_unique": "bC2x8RtY4u", "concept_name": "Blogging for beginners" },
"title_unique": "bT9kL3mN5pQr",
"language": "en",
"status": "complete",
"progress": { "step_process": 3, "is_complete": true },
"is_readonly": false,
"confirmed_at": "2026-10-03T08:00:00Z",
"published_platforms": [],
"created_at": "2026-10-01T03:00:00Z",
"updated_at": "2026-10-03T08:00:00Z"
}
],
"meta": { "total": 1, "current_page": 1, "per_page": 20, "last_page": 1 }
}
コンテンツ詳細
コンテンツ1件の詳細を取得します。package には、各投稿先へ実際に投稿される内容(Stepeee から投稿するときと同じもの)が入ります。投稿(postmode)の投稿一覧はスケジュールで取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
variation_unique |
パス | string | 必須 | — | コンテンツのID |
| 項目 | 型 | 説明 |
|---|---|---|
mode / variation_unique / … / updated_at |
— | コンテンツ一覧と同じ |
publish[] |
object | 投稿先ごとの投稿結果 |
publish[].platform |
string | 投稿先。youtube / tiktok / instagram / x / wordpress / webhook |
publish[].status |
string | 投稿結果。success(投稿済み)/ failed(失敗)/ scheduled(投稿先で予約済み)/ processing(処理中)/ partial_success(投稿は成功し、サムネイル設定などの付随処理が失敗)/ reviewing(投稿は成功し、投稿先の審査待ちでURL未確定) |
publish[].post_url |
string | null | 投稿のURL(未確定なら null) |
publish[].posted_at |
string | null | 投稿日時(未投稿なら null) |
content |
object | モードごとの生成データ。blogmode: body_html(記事本文)/ carouselmode: scenario(スライドの構成。resolved_header・resolved_footer・resolved_texts が掲載言語の文言)/ moviemode: movie_unique・download_url・thumbnail_url(Step3で選択した動画。URLは発行から1時間有効)/ postmode: posts(post_text・post_type) |
package |
object | null | 投稿される内容。postmode は null |
package.video (moviemode) |
object | null | 完成動画 {file: {url, expires_at}, thumbnail: {url, expires_at} | null, duration_ms, width, height, size_bytes}。まだ無ければ null |
package.youtube.title (moviemode) |
string | null | YouTube のタイトル |
package.youtube.description (moviemode) |
string | null | YouTube の説明文(固定文を含む) |
package.youtube.thumbnail (moviemode) |
object | null | YouTube のサムネイル {url, expires_at, width, height}。縦型の動画(ショート)はサムネイルを設定しないため null |
package.tiktok.caption (moviemode) |
string | null | TikTok のキャプション |
package.instagram.caption (moviemode / carouselmode) |
string | null | Instagram のキャプション(固定文を含む) |
package.instagram.cover (moviemode) |
object | null | Instagram のカバー画像 {url, expires_at, width, height} |
package.x.posts (moviemode / blogmode / carouselmode) |
array | X の投稿文。2件以上はスレッドとして順に投稿されます |
package.title (blogmode) |
string | null | 記事タイトル |
package.meta_description (blogmode) |
string | null | メタディスクリプション |
package.body_html (blogmode) |
string | null | 記事本文の HTML。画像は img タグの src に入り、商品紹介のアフィリエイトコードや口コミも置き換え済みです。そのままサイトに掲載できます |
package.images (blogmode) |
array | 本文の画像(出てくる順){url, expires_at, width, height} |
package.cover_image (blogmode) |
object | null | カバー画像 {url, expires_at, width, height} |
package.audio (blogmode) |
object | null | 記事の音声 {url, expires_at, duration_ms} |
package.slides[] (carouselmode) |
object | スライド画像(番号順){no, image: {url, expires_at, width, height}} |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 404 | not_found |
コンテンツが無い(Content not found.) |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/bmA1b2C3d4E5");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"mode": "blogmode",
"variation_unique": "bmA1b2C3d4E5",
"variation_no": 1,
"title": "How to start a blog",
"concept": { "concept_unique": "bC2x8RtY4u", "concept_name": "Blogging for beginners" },
"title_unique": "bT9kL3mN5pQr",
"language": "en",
"status": "complete",
"progress": { "step_process": 3, "is_complete": true },
"is_readonly": false,
"confirmed_at": "2026-10-03T08:00:00Z",
"published_platforms": ["wordpress"],
"created_at": "2026-10-01T03:00:00Z",
"updated_at": "2026-10-03T08:00:00Z",
"publish": [
{
"platform": "wordpress",
"status": "success",
"post_url": "https://blog.example.com/how-to-start-a-blog/",
"posted_at": "2026-10-03T09:00:00Z"
}
],
"content": { "body_html": "<h2>Why start a blog</h2><p>...</p>" },
"package": {
"title": "How to Start a Blog in 2026",
"meta_description": "A step-by-step guide to starting your first blog.",
"body_html": "<h2>Why start a blog</h2><p>...</p><figure><img src=\"https://...\" alt=\"\" /></figure>",
"images": [
{ "url": "https://...", "expires_at": "2026-10-21T10:00:00Z", "width": 1536, "height": 1024 }
],
"cover_image": { "url": "https://...", "expires_at": "2026-10-21T10:00:00Z", "width": 1200, "height": 630 },
"audio": null,
"x": { "posts": ["New post: How to start a blog in 2026"] }
}
}
}
投稿スケジュール
投稿(postmode)のコンテンツの、予定・生成済み・投稿済みの投稿を予定日時の順に取得します。自動化の状況も含みます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
variation_unique |
パス | string | 必須 | — | コンテンツのID |
from |
クエリ | string | 任意 | — | 期間の開始(予定日時)。省略時は今から7日前(to だけ指定した場合は to の37日前) |
to |
クエリ | string | 任意 | — | 期間の終わり(予定日時)。省略時は今から30日後(from だけ指定した場合は from の37日後)。期間は92日まで |
| 項目 | 型 | 説明 |
|---|---|---|
automation.enabled |
boolean | 自動化が有効か |
automation.is_executing |
boolean | 自動で投稿を作る処理が動いているか(自動化を止めても、作成途中の投稿が残っていれば true) |
automation.week_limit |
integer | null | 自動で予定を作る週数の上限(null は無制限) |
automation.week_count |
integer | これまでに予定を作った週数 |
automation.next_refill_at |
string | null | 次に予定を作る日時(自動化が無効なら null) |
automation.timezone |
string | null | 投稿のスケジュールに使うタイムゾーン |
items[].schedule_unique |
string | 予定のID |
items[].post_unique |
string | null | 投稿のID(まだ本文を作っていなければ null) |
items[].scheduled_at |
string | 投稿する予定日時 |
items[].scheduled_at_local |
string | 予定日時(timezone の現地時刻。YYYY-MM-DDTHH:MM:SS) |
items[].timezone |
string | 予定を作ったときのタイムゾーン |
items[].status |
string | 状態。pending(本文の作成待ち)/ generating(作成中)/ generated(作成済み・投稿待ち)/ awaiting_image(画像の作成待ち)/ posting(投稿中)/ posted(投稿済み)/ failed(失敗)/ discarded(取りやめ) |
items[].confirm_state |
string | 投稿前の確認。none(確認なし)/ awaiting(承認されるまで投稿しない)/ notice(通知のみで投稿する)/ confirmed(承認済み) |
items[].created_via |
string | 作られ方。auto(自動化)/ manual(手動) |
items[].post_type |
string | 投稿タイプ。assertion(主張)/ knowhow(ノウハウ)/ experience(体験)/ casual(日常) |
items[].text |
string | null | 投稿の本文(まだ作っていなければ null) |
items[].thread[] |
object | スレッドの続きの投稿(順番どおり){text, post_url, posted_at, image} |
items[].image |
object | null | 添付する画像 {url, expires_at}(無ければ null) |
items[].post_url |
string | null | 投稿のURL(未確定なら null) |
items[].posted_at |
string | null | 投稿日時(未投稿なら null) |
items[].fail_reason |
string | null | 失敗の理由。token_expired(X の連携切れ)/ api_error(X のエラー)/ not_found(投稿の対象が無い)/ insufficient_token(トークン不足)/ no_x_account(X アカウント未設定)/ node_ws_timeout(本文の作成がタイムアウト)/ unconfirmed(承認されなかった) |
meta.from / meta.to |
string | 取得した期間 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 404 | not_found |
投稿(postmode)以外のコンテンツ、またはコンテンツが無い(Schedule not found.) |
| 422 | validation_error |
期間が92日を超える、to が from より前、日時として読めない |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/contents/pmV7d2KqLx01/schedule?from=2026-10-20&to=2026-11-20");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"automation": {
"enabled": true,
"is_executing": true,
"week_limit": 4,
"week_count": 2,
"next_refill_at": "2026-10-26T15:00:00Z",
"timezone": "Asia/Tokyo"
},
"items": [
{
"schedule_unique": "Sc1aB2cD3eF4",
"post_unique": "Po1aB2cD3eF4",
"scheduled_at": "2026-10-20T01:00:00Z",
"scheduled_at_local": "2026-10-20T10:00:00",
"timezone": "Asia/Tokyo",
"status": "posted",
"confirm_state": "none",
"created_via": "auto",
"post_type": "assertion",
"text": "Most teams overthink onboarding...",
"thread": [
{
"text": "First, cut the steps in half.",
"post_url": "https://x.com/i/status/1848000000000000002",
"posted_at": "2026-10-20T01:00:05Z",
"image": null
}
],
"image": { "url": "https://...", "expires_at": "2026-10-21T10:00:00Z" },
"post_url": "https://x.com/i/status/1848000000000000001",
"posted_at": "2026-10-20T01:00:00Z",
"fail_reason": null
},
{
"schedule_unique": "Sc9zY8xW7vU6",
"post_unique": null,
"scheduled_at": "2026-10-25T09:30:00Z",
"scheduled_at_local": "2026-10-25T18:30:00",
"timezone": "Asia/Tokyo",
"status": "pending",
"confirm_state": "none",
"created_via": "auto",
"post_type": "knowhow",
"text": null,
"thread": [],
"image": null,
"post_url": null,
"posted_at": null,
"fail_reason": null
}
]
},
"meta": { "from": "2026-10-20T00:00:00Z", "to": "2026-11-20T23:59:59Z" }
}
投稿結果・連携先
SNS・WordPress・Webhook への投稿結果と、プロジェクトに連携している投稿先の状態を取得します。連携切れの検知に使えます。
投稿結果一覧
プロジェクトの投稿結果を、すべてのモードと投稿先を横断して新しい順に取得します。投稿(postmode)は、投稿済みと失敗した投稿(スレッドの最初の投稿)を含みます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
mode |
クエリ | string | 任意 | — | モードで絞り込みます。moviemode(動画)・blogmode(ブログ)・carouselmode(カルーセル)・postmode(投稿)をカンマ区切りで複数指定できます。省略時はすべて |
platform |
クエリ | string | 任意 | — | 投稿先で絞り込みます(カンマ区切り)。youtube / tiktok / instagram / x / wordpress / webhook |
status |
クエリ | string | 任意 | — | 投稿結果で絞り込みます(カンマ区切り)。success / failed / scheduled / processing / partial_success / reviewing |
from |
クエリ | string | 任意 | — | 投稿日時(未投稿なら記録日時)がこの日時以降のものだけを返します |
to |
クエリ | string | 任意 | — | 投稿日時(未投稿なら記録日時)がこの日時以前のものだけを返します |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].publication_unique |
string | 投稿結果のID |
data[].mode |
string | moviemode(動画)/ blogmode(ブログ)/ carouselmode(カルーセル)/ postmode(投稿) |
data[].content.variation_unique |
string | コンテンツのID |
data[].content.title |
string | null | タイトル(postmode はコンセプト名) |
data[].platform |
string | 投稿先。youtube / tiktok / instagram / x / wordpress / webhook |
data[].account |
object | null | 投稿したアカウント {account_unique, name}。連携を解除したアカウントは name が null。postmode は null |
data[].status |
string | 投稿結果。success(投稿済み)/ failed(失敗)/ scheduled(投稿先で予約済み)/ processing(処理中)/ partial_success(投稿は成功し、サムネイル設定などの付随処理が失敗)/ reviewing(投稿は成功し、投稿先の審査待ちでURL未確定) |
data[].post_url |
string | null | 投稿のURL(未確定なら null) |
data[].error_code |
string | null | 失敗の理由のコード(投稿先やモードごとに異なります) |
data[].is_automation |
boolean | 自動化で投稿したか |
data[].posted_at |
string | null | 投稿日時(未投稿なら null) |
data[].created_at |
string | 作成日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/publications?platform=x,youtube&status=failed");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"publication_unique": "Xk3p9QmZ2aLw",
"mode": "postmode",
"content": { "variation_unique": "pmV7d2KqLx01", "title": "SaaS growth tips" },
"platform": "x",
"account": null,
"status": "success",
"post_url": "https://x.com/i/status/1848123456789012345",
"error_code": null,
"is_automation": true,
"posted_at": "2026-10-04T10:00:00Z",
"created_at": "2026-10-03T22:10:00Z"
},
{
"publication_unique": "Pq2wE4rT6yUi",
"mode": "blogmode",
"content": { "variation_unique": "bmA1b2C3d4E5", "title": "How to start a blog" },
"platform": "wordpress",
"account": { "account_unique": "Wp3xY5zA7bCd", "name": "My WP Site" },
"status": "failed",
"post_url": null,
"error_code": "auth_failed",
"is_automation": false,
"posted_at": null,
"created_at": "2026-10-02T10:00:00Z"
}
],
"meta": { "total": 2, "current_page": 1, "per_page": 20, "last_page": 1 }
}
連携先一覧
プロジェクトに連携している投稿先(SNS アカウント・WordPress・Webhook)と、その状態を取得します。status が expired や connection_error になったら再連携が必要です。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
| 項目 | 型 | 説明 |
|---|---|---|
data[].account_unique |
string | 連携先のID |
data[].platform |
string | 投稿先。youtube / tiktok / instagram / x / wordpress / webhook |
data[].name |
string | 表示名。SNS はアカウント名、WordPress はサイト名、Webhook は送信先URLのドメイン(https://example.com/… の形。パスは含みません) |
data[].image_url |
string | null | アカウントのアイコン画像のURL(SNS のみ) |
data[].status |
string | 状態。active(利用可能)/ expired(連携の期限切れ。再連携が必要)/ connection_error(WordPress に接続できない) |
data[].token_expires_at |
string | null | 連携の有効期限(SNS のみ) |
data[].connected_at |
string | null | 連携した日時 |
data[].last_used_at |
string | null | 最後に投稿に使った日時(SNS のみ) |
data[].site_url |
string | null | WordPress のサイトURL(WordPress のみ) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
curl "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/a1b2c3d4e5/accounts");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"account_unique": "Wh9kQ2mN4pRt",
"platform": "webhook",
"name": "https://hooks.example.com/…",
"image_url": null,
"status": "active",
"token_expires_at": null,
"connected_at": "2026-07-01T00:00:00Z",
"last_used_at": null,
"site_url": null
},
{
"account_unique": "Wp3xY5zA7bCd",
"platform": "wordpress",
"name": "Example Blog",
"image_url": null,
"status": "connection_error",
"token_expires_at": null,
"connected_at": "2026-08-01T00:00:00Z",
"last_used_at": null,
"site_url": "https://blog.example.com"
},
{
"account_unique": "Yt4aB6cD8eFg",
"platform": "youtube",
"name": "Channel B",
"image_url": "https://yt3.ggpht.com/abc.png",
"status": "expired",
"token_expires_at": "2026-10-01T00:00:00Z",
"connected_at": "2026-09-01T00:00:00Z",
"last_used_at": "2026-09-30T00:00:00Z",
"site_url": null
}
]
}
自動化
動画・ブログ・カルーセルの自動化の実行状況を取得します。投稿の自動化(ポストモード)の状況は、コンテンツのスケジュールで取得します。
自動化の実行一覧
動画・ブログ・カルーセルの自動化の実行(予約・実行中・確認待ち・終了)を新しい順に取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
status |
クエリ | string | 任意 | — | 状態で絞り込みます(カンマ区切り)。値は data[].status と同じ |
mode |
クエリ | string | 任意 | — | モードで絞り込みます(カンマ区切り)。moviemode / blogmode / carouselmode |
project_unique |
クエリ | string | 任意 | — | このプロジェクトの実行だけを返します |
from |
クエリ | string | 任意 | — | 作成日時がこの日時以降のものだけを返します |
to |
クエリ | string | 任意 | — | 作成日時がこの日時以前のものだけを返します |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].auto_unique |
string | 自動化の実行のID |
data[].mode |
string | moviemode / blogmode / carouselmode |
data[].project |
object | プロジェクト {project_unique, project_name} |
data[].content.variation_unique |
string | コンテンツのID |
data[].content.title |
string | null | タイトル(postmode はコンセプト名) |
data[].run_no |
integer | そのコンテンツで何回目の実行か |
data[].status |
string | 状態。pending(実行待ち。reserved_at が未来なら予約)/ executing(実行中)/ waiting_confirmation(内容の確認待ち。確認すると続きを実行)/ completed(完了)/ failed(失敗)/ stopped(停止)/ token_shortage(トークン不足で終了) |
data[].execution_mode |
string | sequential(1件ずつ実行)/ parallel(同時に実行) |
data[].phases |
object | 段階ごとの状態 {setup, step1, step2, step3}。not_started(未着手)/ running(実行中、または止まった段階)/ done(完了。スキップ、および completed した run では自動化の範囲外にした手順も含む)/ error(失敗) |
data[].template.setup_template_name |
string | null | 開始時に使ったセットアップテンプレートの名前 |
data[].template.automation_template_name |
string | null | 開始時に使った自動化テンプレートの名前 |
data[].reserved_at |
string | null | 予約した実行日時 |
data[].executed_at |
string | null | 実行を始めた日時 |
data[].completed_at |
string | null | 終了した日時(completed / failed / stopped / token_shortage のとき) |
data[].created_at |
string | 実行を登録した日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/automations?status=executing,waiting_confirmation");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"auto_unique": "aB3dE5fG7h",
"mode": "blogmode",
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My Blog" },
"content": { "variation_unique": "Xy12Zw34Ab56", "title": "Spring travel tips" },
"run_no": 2,
"status": "executing",
"execution_mode": "sequential",
"phases": { "setup": "done", "step1": "done", "step2": "running", "step3": "not_started" },
"template": { "setup_template_name": "Default setup", "automation_template_name": null },
"reserved_at": null,
"executed_at": "2026-10-19T23:09:27Z",
"completed_at": null,
"created_at": "2026-10-19T23:09:20Z"
}
],
"meta": { "total": 1, "current_page": 1, "per_page": 20, "last_page": 1 }
}
自動化の実行詳細
自動化の実行1件の詳細と、手順ごとの進み具合を取得します。実行中の進捗を確かめるときに使えます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
auto_unique |
パス | string | 必須 | — | 自動化の実行のID |
| 項目 | 型 | 説明 |
|---|---|---|
auto_unique / mode / … / created_at |
— | 自動化の実行一覧と同じ |
steps[].key |
string | 手順の名前(例: step1_1_text) |
steps[].phase |
string | 手順の段階。setup / step1 / step2 / step3 |
steps[].status |
string | 手順の状態。not_run(未実行・対象外・実行中)/ success(成功)/ error(失敗)/ skipped(スキップ) |
steps[].started_at |
string | null | 実行中の手順が始まった日時(終わると null) |
steps[].finished_at |
string | null | 手順が終わった日時 |
steps[].duration_sec |
number | null | かかった秒数(success / error のとき) |
steps[].error_code |
string | null | 失敗の理由。internal_error / automation_record_not_found / automation_stopped_by_admin / insufficient_token(トークン不足)/ token_group_blocked(チームの利用枠の上限)/ automation_auth_error(投稿先の認証エラー)/ automation_not_found / automation_conflict / automation_rate_limited(投稿先の回数制限)/ automation_server_error(投稿先のエラー)/ automation_network_error(通信エラー)/ automation_step_failed。理由が記録されていなければ null |
accounts[] |
object | 開始時の投稿先 {platform, account_unique, name}。Webhook の name は null |
stop_requested |
boolean | 停止を指示したか |
confirmation.requested_at |
string | null | 確認待ちになった日時 |
confirmation.confirmed_at |
string | null | 内容を確認した日時(確認待ちや未確認は null) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
自動化が無い、または取得できる範囲外(Automation not found.) |
curl "https://stepeee.com/public-api/v1/automations/aB3dE5fG7h" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/automations/aB3dE5fG7h",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations/aB3dE5fG7h", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations/aB3dE5fG7h")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations/aB3dE5fG7h"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/automations/aB3dE5fG7h");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"auto_unique": "aB3dE5fG7h",
"mode": "blogmode",
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My Blog" },
"content": { "variation_unique": "Xy12Zw34Ab56", "title": "Spring travel tips" },
"run_no": 2,
"status": "failed",
"execution_mode": "sequential",
"phases": { "setup": "done", "step1": "done", "step2": "done", "step3": "error" },
"template": { "setup_template_name": "Default setup", "automation_template_name": "Skip voice" },
"reserved_at": null,
"executed_at": "2026-10-19T23:09:27Z",
"completed_at": "2026-10-19T23:17:50Z",
"created_at": "2026-10-19T23:09:20Z",
"steps": [
{ "key": "setup", "phase": "setup", "status": "success", "started_at": null, "finished_at": "2026-10-19T23:09:29Z", "duration_sec": 2.3, "error_code": null },
{ "key": "step1_1_text", "phase": "step1", "status": "success", "started_at": null, "finished_at": "2026-10-19T23:11:40Z", "duration_sec": 126.3, "error_code": null },
{ "key": "step2_2", "phase": "step2", "status": "skipped", "started_at": null, "finished_at": "2026-10-19T23:17:39Z", "duration_sec": null, "error_code": null },
{ "key": "step3_4_webhook", "phase": "step3", "status": "error", "started_at": null, "finished_at": "2026-10-19T23:17:46Z", "duration_sec": 1.2, "error_code": "automation_server_error" }
],
"accounts": [
{ "platform": "webhook", "account_unique": "dxuD2gk3NYuA", "name": null }
],
"stop_requested": false,
"confirmation": { "requested_at": null, "confirmed_at": null }
}
}
素材・テンプレート
MY素材(画像・映像・BGM)と、セットアップ・自動化のテンプレートを取得します。
-
素材一覧
GET /materials -
素材詳細
GET /materials/{material_unique} -
素材カテゴリ一覧
GET /material-categories -
テンプレート一覧
GET /templates
素材一覧
MY素材(画像・映像・BGM)を新しい順に取得します。チームでは、チームで共有している素材を返します。プロジェクトの中だけで使う画像や生成途中のファイルは含みません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
kind |
クエリ | string | 任意 | — | 素材の種類で絞り込みます。image(画像)/ video(映像)/ bgm |
type |
クエリ | string | 任意 | — | 素材の用途で絞り込みます。値は data[].type と同じ。kind と一緒に指定する場合は、その種類の用途だけを指定できます |
category_unique |
クエリ | string | 任意 | — | このカテゴリの素材だけを返します |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].material_unique |
string | 素材のID |
data[].kind |
string | 種類。image(画像)/ video(映像)/ bgm |
data[].type |
string | 用途。image_element(エレメント)/ image_vertical(縦)/ image_horizontal(横)/ reference_person(参照画像: 人物)/ reference_background(参照画像: 背景)/ reference_layout(参照画像: レイアウト)/ reference_cta(参照画像: CTA)/ reference_pet(参照画像: ペット)/ reference_product(参照画像: 商品・サービス)/ image_rulebook(ルールブック)/ image_promotion(プロモーション)/ video_vertical(縦の映像)/ video_horizontal(横の映像)/ bgm |
data[].category |
object | null | カテゴリ {category_unique, name}(未分類なら null) |
data[].width / data[].height |
integer | null | 幅と高さ(ピクセル)。BGM と未計測は null |
data[].duration_ms |
integer | null | 長さ(ミリ秒)。画像は null |
data[].size_bytes |
integer | ファイルサイズ(バイト)。共有素材を参照している場合は 0 のことがあります |
data[].file |
object | ファイル本体 {url, expires_at} |
data[].thumbnail |
object | null | サムネイル {url, expires_at}。BGM・エレメント・サムネイルの作成中は null |
data[].created_at |
string | 作成日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/materials?kind=image&type=image_vertical");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"material_unique": "aB3dE5fG7hJ9kL1mN3pQ",
"kind": "image",
"type": "image_vertical",
"category": { "category_unique": "Xy12Ab34Cd", "name": "Product shots" },
"width": 768,
"height": 1344,
"duration_ms": null,
"size_bytes": 1234567,
"file": { "url": "https://...", "expires_at": "2026-10-21T11:00:00Z" },
"thumbnail": { "url": "https://...", "expires_at": "2026-10-21T11:00:00Z" },
"created_at": "2026-10-01T10:00:00Z"
},
{
"material_unique": "Zq9Wv8Ut7Sr6Qp5On4Ml",
"kind": "bgm",
"type": "bgm",
"category": null,
"width": null,
"height": null,
"duration_ms": 30000,
"size_bytes": 482133,
"file": { "url": "https://...", "expires_at": "2026-10-21T11:00:00Z" },
"thumbnail": null,
"created_at": "2026-09-30T08:12:00Z"
}
],
"meta": { "total": 2, "current_page": 1, "per_page": 20, "last_page": 1 }
}
素材詳細
素材1件を取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
material_unique |
パス | string | 必須 | — | 素材のID |
| 項目 | 型 | 説明 |
|---|---|---|
material_unique |
string | 素材のID |
kind |
string | 種類。image(画像)/ video(映像)/ bgm |
type |
string | 用途。image_element(エレメント)/ image_vertical(縦)/ image_horizontal(横)/ reference_person(参照画像: 人物)/ reference_background(参照画像: 背景)/ reference_layout(参照画像: レイアウト)/ reference_cta(参照画像: CTA)/ reference_pet(参照画像: ペット)/ reference_product(参照画像: 商品・サービス)/ image_rulebook(ルールブック)/ image_promotion(プロモーション)/ video_vertical(縦の映像)/ video_horizontal(横の映像)/ bgm |
category |
object | null | カテゴリ {category_unique, name}(未分類なら null) |
width / height |
integer | null | 幅と高さ(ピクセル)。BGM と未計測は null |
duration_ms |
integer | null | 長さ(ミリ秒)。画像は null |
size_bytes |
integer | ファイルサイズ(バイト)。共有素材を参照している場合は 0 のことがあります |
file |
object | ファイル本体 {url, expires_at} |
thumbnail |
object | null | サムネイル {url, expires_at}。BGM・エレメント・サムネイルの作成中は null |
created_at |
string | 作成日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
素材が無い、または取得できる範囲外(Material not found.) |
curl "https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/materials/aB3dE5fG7hJ9kL1mN3pQ");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"material_unique": "aB3dE5fG7hJ9kL1mN3pQ",
"kind": "image",
"type": "image_vertical",
"category": { "category_unique": "Xy12Ab34Cd", "name": "Product shots" },
"width": 768,
"height": 1344,
"duration_ms": null,
"size_bytes": 1234567,
"file": { "url": "https://...", "expires_at": "2026-10-21T11:00:00Z" },
"thumbnail": { "url": "https://...", "expires_at": "2026-10-21T11:00:00Z" },
"created_at": "2026-10-01T10:00:00Z"
}
}
素材カテゴリ一覧
素材のカテゴリと、カテゴリごとの素材数を取得します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
kind |
クエリ | string | 任意 | — | 素材の種類で絞り込みます。image(画像)/ video(映像)/ bgm |
type |
クエリ | string | 任意 | — | 素材の用途で絞り込みます。値は data[].type と同じ。kind と一緒に指定する場合は、その種類の用途だけを指定できます |
| 項目 | 型 | 説明 |
|---|---|---|
data[].category_unique |
string | カテゴリのID |
data[].name |
string | カテゴリ名 |
data[].kind |
string | 種類。image(画像)/ video(映像)/ bgm |
data[].type |
string | 用途。image_element(エレメント)/ image_vertical(縦)/ image_horizontal(横)/ reference_person(参照画像: 人物)/ reference_background(参照画像: 背景)/ reference_layout(参照画像: レイアウト)/ reference_cta(参照画像: CTA)/ reference_pet(参照画像: ペット)/ reference_product(参照画像: 商品・サービス)/ image_rulebook(ルールブック)/ image_promotion(プロモーション)/ video_vertical(縦の映像)/ video_horizontal(横の映像)/ bgm |
data[].is_system |
boolean | Stepeee が自動で作ったカテゴリか |
data[].material_count |
integer | カテゴリの素材数 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/material-categories?kind=image" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/material-categories?kind=image",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/material-categories?kind=image", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/material-categories?kind=image")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/material-categories?kind=image"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/material-categories?kind=image");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"category_unique": "Bg12Ab34Cd",
"name": "Lo-fi",
"kind": "bgm",
"type": "bgm",
"is_system": false,
"material_count": 3
},
{
"category_unique": "Xy12Ab34Cd",
"name": "Product shots",
"kind": "image",
"type": "image_vertical",
"is_system": false,
"material_count": 12
}
]
}
テンプレート一覧
セットアップテンプレートと自動化テンプレートを、更新が新しい順に取得します。チームでは、チームで共有しているテンプレートを返します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
mode |
クエリ | string | 任意 | — | モードで絞り込みます。moviemode / blogmode / carouselmode / postmode |
kind |
クエリ | string | 任意 | — | テンプレートの種類で絞り込みます。setup / automation |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].template_unique |
string | テンプレートのID |
data[].kind |
string | 種類。setup(制作の設定をまとめたセットアップテンプレート)/ automation(自動化で実行する手順を決める自動化テンプレート) |
data[].mode |
string | moviemode(動画)/ blogmode(ブログ)/ carouselmode(カルーセル)/ postmode(投稿) |
data[].name |
string | テンプレート名 |
data[].created_at |
string | 作成日時 |
data[].updated_at |
string | 更新日時 |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/templates?kind=setup&mode=moviemode");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"template_unique": "Ab12Cd34Ef",
"kind": "automation",
"mode": "carouselmode",
"name": "Morning carousel",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-10-05T00:00:00Z"
},
{
"template_unique": "Gh56Ij78Kl",
"kind": "setup",
"mode": "moviemode",
"name": "60-second explainer",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-10-01T00:00:00Z"
}
],
"meta": { "total": 2, "current_page": 1, "per_page": 20, "last_page": 1 }
}
タイトル・コンテンツ
動画・ブログ・カルーセルのコンセプトにタイトルを追加し、コンテンツを削除します。Pro プラン以上で使えます。
-
タイトルを追加する
POST /projects/{project_unique}/concepts/{concept_unique}/titles -
コンテンツを削除する
DELETE /projects/{project_unique}/contents/{variation_unique}
タイトルを追加する
動画・ブログ・カルーセルのコンセプトにタイトルをまとめて追加し、タイトルごとに最初のコンテンツを1件作ります(画面でタイトルを手動で登録したときと同じ処理)。同じコンセプトに同じ名前のタイトルがあるもの、同じリクエストの中で2回目以降に出てくる名前は作らずに skipped に入れます。コンセプトのタイトルは100件までで、追加すると100件を超える場合は1件も作りません(同じ名前で作らないものは数えません)。プランのコンテンツ数の上限で作れないときは、タイトルだけを作り variation_unique を null にします。ブログのプロモーション・アフィリエイトの設定はできず、標準の記事として作ります。チームでは、作ったタイトルとコンテンツの所有者はチームのオーナーです。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
concept_unique |
パス | string | 必須 | — | コンセプトのID(動画・ブログ・カルーセルのコンセプトで、プロジェクトの中にあるもの) |
titles |
本文 | string[] | 必須 | — | 追加するタイトル。1〜50件。それぞれ前後の空白を除いて1〜500文字(空白だけ・「0」だけ・途中に改行を含むものは不可) |
language |
本文 | string | 必須 | — | 作るコンテンツの掲載言語(ja、en、fr などの言語コード) |
setup_template_unique |
本文 | string | null | 任意 | — | 適用するセットアップテンプレートのID(GET /templates の template_unique。kind が setup で、コンセプトと同じモードのもの)。省略するとコンセプトの既定のテンプレート(未設定なら標準のセットアップ) |
Idempotency-Key |
ヘッダー | string | 任意 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
created[] |
object | 作ったタイトル(送った順) |
created[].title_unique |
string | タイトルのID |
created[].title_name |
string | タイトル名(前後の空白を除いたもの) |
created[].variation_unique |
string | null | 作った最初のコンテンツのID。プランのコンテンツ数の上限で作れなかったときは null |
skipped[] |
object | 作らなかったタイトル(送った順) |
skipped[].title_name |
string | タイトル名(前後の空白を除いたもの) |
skipped[].reason |
string | 作らなかった理由。duplicate(同じコンセプトに同じ名前のタイトルがある、または同じリクエストの中で2回目以降に出てきた) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 403 | readonly |
プロジェクトがプランのダウングレードで閲覧専用 |
| 404 | not_found |
プロジェクトが無い・取得できる範囲外、またはコンセプトがそのプロジェクトに無い |
| 409 | title_limit_reached |
追加するとコンセプトのタイトルが100件を超える(1件も作りません)。details に limit(上限)と total_after_add(追加後の件数) |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | validation_error |
パラメータが不正 |
| 422 | mode_not_supported |
投稿(ポストモード)またはフォトのコンセプト |
| 422 | template_not_found |
setup_template_unique のテンプレートが無い(別のモードのものを含む) |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
curl -X POST "https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90" \
-d '{
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}'
import requests
body = """{
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}"""
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
body: JSON.stringify({
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
request.httpBody = """
{
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"titles": ["Easy breakfast for beginners", "Meal prep in 5 minutes", "Easy breakfast for beginners"],
"language": "en",
"setup_template_unique": "Gh56Ij78Kl"
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/concepts/Cx2Yz4Wv6Ut8/titles");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"created": [
{ "title_unique": "q8Wm2LzR0pXa", "title_name": "Easy breakfast for beginners", "variation_unique": "Hn4kT7sY1cVb" },
{ "title_unique": "Zr5uP9eK3wQd", "title_name": "Meal prep in 5 minutes", "variation_unique": "Jm8oB2fN6xLe" }
],
"skipped": [
{ "title_name": "Easy breakfast for beginners", "reason": "duplicate" }
]
}
}
コンテンツを削除する
動画・ブログ・カルーセルのコンテンツを削除します(画面でコンテンツを削除したときと同じ処理)。削除したコンテンツはすぐに一覧・詳細から消え、delete_at(3日後)を過ぎると、生成した画像・音声・動画とともに完全に削除されます。同じタイトルの後ろのコンテンツの番号は1つずつ詰めます。自動化の実行中・予約中のコンテンツは削除できないので、自動化を止めてから削除してください。タイトルに残る最後の1件と、投稿(ポストモード)のコンテンツは削除できません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
project_unique |
パス | string | 必須 | — | プロジェクトのID |
variation_unique |
パス | string | 必須 | — | コンテンツのID |
| 項目 | 型 | 説明 |
|---|---|---|
variation_unique |
string | 削除したコンテンツのID |
mode |
string | moviemode(動画)/ blogmode(ブログ)/ carouselmode(カルーセル) |
delete_at |
string | 完全に削除される日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 403 | readonly |
コンテンツまたはプロジェクトがプランのダウングレードで閲覧専用 |
| 404 | not_found |
プロジェクトが無い・取得できる範囲外、コンテンツがそのプロジェクトに無い、または削除済み |
| 409 | automation_running |
自動化の実行中・予約中(終わっていない自動化がある) |
| 409 | last_variation |
タイトルに残る最後の1件 |
| 422 | mode_not_supported |
投稿(ポストモード)のコンテンツ |
curl -X DELETE "https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.request(
"DELETE",
"https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb", {
method: "DELETE",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb")!)
request.httpMethod = "DELETE"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/projects/Pq7Rs9Tu1V/contents/Hn4kT7sY1cVb");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"variation_unique": "Hn4kT7sY1cVb",
"mode": "blogmode",
"delete_at": "2026-10-24T12:00:00Z"
}
}
自動化の操作
動画・ブログ・カルーセルの自動化を開始・予約変更・停止し、確認待ちの自動化を承認します。操作できるのは GET /automations で取得できる自動化と同じ範囲です。停止はプランに関係なく使え、それ以外は Pro プラン以上で使えます。
-
自動化を開始する
POST /automations -
予約日時を変更する
PATCH /automations/{auto_unique} -
自動化を停止する
POST /automations/{auto_unique}/stop -
確認待ちを承認する
POST /automations/{auto_unique}/confirm
自動化を開始する
コンテンツ(動画・ブログ・カルーセル)の自動化を、自動化テンプレートの設定で開始します。reserved_at を指定すると予約、省略すると今すぐ実行します。対象はすべて同じプロジェクト・同じモードのコンテンツにしてください。1件でも開始できないコンテンツがあれば何も登録せず、どのコンテンツが何の理由で開始できないかを返します。作成済みの手順は飛ばして最初の未作成の手順から実行し、自動化テンプレートでスキップにした手順は実行しません。セットアップが未完了のコンテンツは、開始時にセットアップを確定します。自動化の実行では Token を消費します。開始時には残高を確かめず、実行中に足りなくなると token_shortage で終わります。内容の確認が必要な設定では途中で waiting_confirmation になって止まるので、POST /automations/{auto_unique}/confirm で承認してください。投稿(ポストモード)の自動投稿は、コンテンツごとに画面でオン・オフする別の仕組みで、このエンドポイントでは開始できません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
variation_uniques |
本文 | string[] | 必須 | — | 自動化するコンテンツの variation_unique。1〜50件、重複不可 |
automation_template_unique |
本文 | string | 必須 | — | 自動化テンプレートのID(GET /templates?kind=automation の template_unique。コンテンツと同じモードのもの) |
reserved_at |
本文 | string | 任意 | — | 実行する日時(未来の日時)。時差つきの ISO 8601 で指定し、時差が無いものは UTC として扱います。省略すると今すぐ実行します |
Idempotency-Key |
ヘッダー | string | 必須 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。二重に開始しないよう必須です。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].auto_unique |
string | 自動化の実行のID |
data[].mode |
string | moviemode / blogmode / carouselmode |
data[].project |
object | プロジェクト {project_unique, project_name} |
data[].content.variation_unique |
string | コンテンツのID |
data[].content.title |
string | null | タイトル(postmode はコンセプト名) |
data[].run_no |
integer | そのコンテンツで何回目の実行か |
data[].status |
string | 状態。pending(実行待ち。reserved_at が未来なら予約)/ executing(実行中)/ waiting_confirmation(内容の確認待ち。確認すると続きを実行)/ completed(完了)/ failed(失敗)/ stopped(停止)/ token_shortage(トークン不足で終了) |
data[].execution_mode |
string | sequential(1件ずつ実行)/ parallel(同時に実行) |
data[].phases |
object | 段階ごとの状態 {setup, step1, step2, step3}。not_started(未着手)/ running(実行中、または止まった段階)/ done(完了。スキップ、および completed した run では自動化の範囲外にした手順も含む)/ error(失敗) |
data[].template.setup_template_name |
string | null | 開始時に使ったセットアップテンプレートの名前 |
data[].template.automation_template_name |
string | null | 開始時に使った自動化テンプレートの名前 |
data[].reserved_at |
string | null | 予約した実行日時 |
data[].executed_at |
string | null | 実行を始めた日時 |
data[].completed_at |
string | null | 終了した日時(completed / failed / stopped / token_shortage のとき) |
data[].created_at |
string | 実行を登録した日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 404 | content_not_found |
取得できる範囲のコンテンツに無い variation_unique がある(受け付けた後に削除予約されたものを含む。何も登録しません)。details.variation_uniques に該当するもの |
| 404 | automation_template_not_found |
自動化テンプレートが無い |
| 409 | contents_not_automatable |
開始できないコンテンツがある(何も登録しません)。details.contents に {variation_unique, reason} の配列。reason は automation_active(終わっていない自動化がある)/ content_complete(完成済み)/ content_readonly(プランのダウングレードで閲覧専用)/ layout_template_required(カルーセルで、プロジェクトにレイアウトテンプレートが1件も無い) |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | validation_error |
パラメータが不正(0件・51件以上、重複、reserved_at が過去など) |
| 422 | mode_not_supported |
投稿(ポストモード)のコンテンツが含まれる。details.variation_uniques に該当するもの |
| 422 | mixed_modes |
モードの違うコンテンツが混ざっている |
| 422 | mixed_projects |
プロジェクトの違うコンテンツが混ざっている |
| 422 | automation_template_mode_mismatch |
自動化テンプレートのモードがコンテンツのモードと違う |
| 422 | idempotency_key_required |
Idempotency-Key ヘッダーが無い |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
| 503 | automation_dispatch_failed |
今すぐ実行の開始に失敗した。登録した自動化は failed になります。同じ Idempotency-Key で再送すると、新しく登録し直して開始します |
curl -X POST "https://stepeee.com/public-api/v1/automations" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90" \
-d '{
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}'
import requests
body = """{
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}"""
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/automations",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
body: JSON.stringify({
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
request.httpBody = """
{
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"variation_uniques": ["Ab3dEf6hIj9k", "Lm2nOp5qRs8t"],
"automation_template_unique": "Tm7pL2xQ9z",
"reserved_at": "2030-01-02T12:04:05+09:00"
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/automations");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"auto_unique": "Qw3eRt6yUi",
"mode": "blogmode",
"project": { "project_unique": "Pj8kL3mN2b", "project_name": "My Project" },
"content": { "variation_unique": "Ab3dEf6hIj9k", "title": "My blog title" },
"run_no": 1,
"status": "pending",
"execution_mode": "sequential",
"phases": { "setup": "running", "step1": "not_started", "step2": "not_started", "step3": "not_started" },
"template": { "setup_template_name": null, "automation_template_name": "Morning blog" },
"reserved_at": "2030-01-02T03:04:05Z",
"executed_at": null,
"completed_at": null,
"created_at": "2026-10-21T10:00:00Z"
},
{
"auto_unique": "As4dFg7hJk",
"mode": "blogmode",
"project": { "project_unique": "Pj8kL3mN2b", "project_name": "My Project" },
"content": { "variation_unique": "Lm2nOp5qRs8t", "title": "My blog title" },
"run_no": 1,
"status": "pending",
"execution_mode": "sequential",
"phases": { "setup": "running", "step1": "not_started", "step2": "not_started", "step3": "not_started" },
"template": { "setup_template_name": null, "automation_template_name": "Morning blog" },
"reserved_at": "2030-01-02T03:04:05Z",
"executed_at": null,
"completed_at": null,
"created_at": "2026-10-21T10:00:00Z"
}
]
}
予約日時を変更する
実行待ち(status が pending)の自動化の実行日時を変更します。実行が始まったもの・終了したものは変更できません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
auto_unique |
パス | string | 必須 | — | 自動化の実行のID |
reserved_at |
本文 | string | 必須 | — | 新しい実行日時(未来の日時)。時差つきの ISO 8601 で指定し、時差が無いものは UTC として扱います |
| 項目 | 型 | 説明 |
|---|---|---|
auto_unique |
string | 自動化の実行のID |
mode |
string | moviemode / blogmode / carouselmode |
project |
object | プロジェクト {project_unique, project_name} |
content.variation_unique |
string | コンテンツのID |
content.title |
string | null | タイトル(postmode はコンセプト名) |
run_no |
integer | そのコンテンツで何回目の実行か |
status |
string | 状態。pending(実行待ち。reserved_at が未来なら予約)/ executing(実行中)/ waiting_confirmation(内容の確認待ち。確認すると続きを実行)/ completed(完了)/ failed(失敗)/ stopped(停止)/ token_shortage(トークン不足で終了) |
execution_mode |
string | sequential(1件ずつ実行)/ parallel(同時に実行) |
phases |
object | 段階ごとの状態 {setup, step1, step2, step3}。not_started(未着手)/ running(実行中、または止まった段階)/ done(完了。スキップ、および completed した run では自動化の範囲外にした手順も含む)/ error(失敗) |
template.setup_template_name |
string | null | 開始時に使ったセットアップテンプレートの名前 |
template.automation_template_name |
string | null | 開始時に使った自動化テンプレートの名前 |
reserved_at |
string | null | 予約した実行日時 |
executed_at |
string | null | 実行を始めた日時 |
completed_at |
string | null | 終了した日時(completed / failed / stopped / token_shortage のとき) |
created_at |
string | 実行を登録した日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 404 | not_found |
自動化が無い、または取得できる範囲外(Automation not found.) |
| 409 | automation_not_pending |
実行待ち(pending)ではない(実行が始まった、または終了した) |
| 422 | validation_error |
reserved_at が無い・日時として読めない・過去 |
curl -X PATCH "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"reserved_at": "2031-05-06T07:08:09+09:00"
}'
import requests
body = """{
"reserved_at": "2031-05-06T07:08:09+09:00"
}"""
response = requests.request(
"PATCH",
"https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi", {
method: "PATCH",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
"reserved_at": "2031-05-06T07:08:09+09:00"
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi")!)
request.httpMethod = "PATCH"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = """
{
"reserved_at": "2031-05-06T07:08:09+09:00"
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString("""
{
"reserved_at": "2031-05-06T07:08:09+09:00"
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"reserved_at": "2031-05-06T07:08:09+09:00"
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"auto_unique": "Qw3eRt6yUi",
"mode": "blogmode",
"project": { "project_unique": "Pj8kL3mN2b", "project_name": "My Project" },
"content": { "variation_unique": "Ab3dEf6hIj9k", "title": "My blog title" },
"run_no": 1,
"status": "pending",
"execution_mode": "sequential",
"phases": { "setup": "running", "step1": "not_started", "step2": "not_started", "step3": "not_started" },
"template": { "setup_template_name": null, "automation_template_name": "Morning blog" },
"reserved_at": "2031-05-05T22:08:09Z",
"executed_at": null,
"completed_at": null,
"created_at": "2026-10-21T10:00:00Z"
}
}
自動化を停止する
画面の停止と同じ操作です。プランに関係なく使えます(プランを変えたあとも止められます)。実行待ち(予約中を含む)と確認待ちは、その場で stopped になります。実行中は停止を依頼し、応答の時点では executing のままで、実行中の手順の区切りで stopped になります(GET /automations/{auto_unique} で確認してください)。終了済みのものは何もせず、そのままの状態を返します。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
auto_unique |
パス | string | 必須 | — | 自動化の実行のID |
| 項目 | 型 | 説明 |
|---|---|---|
auto_unique |
string | 自動化の実行のID |
mode |
string | moviemode / blogmode / carouselmode |
project |
object | プロジェクト {project_unique, project_name} |
content.variation_unique |
string | コンテンツのID |
content.title |
string | null | タイトル(postmode はコンセプト名) |
run_no |
integer | そのコンテンツで何回目の実行か |
status |
string | 状態。pending(実行待ち。reserved_at が未来なら予約)/ executing(実行中)/ waiting_confirmation(内容の確認待ち。確認すると続きを実行)/ completed(完了)/ failed(失敗)/ stopped(停止)/ token_shortage(トークン不足で終了) |
execution_mode |
string | sequential(1件ずつ実行)/ parallel(同時に実行) |
phases |
object | 段階ごとの状態 {setup, step1, step2, step3}。not_started(未着手)/ running(実行中、または止まった段階)/ done(完了。スキップ、および completed した run では自動化の範囲外にした手順も含む)/ error(失敗) |
template.setup_template_name |
string | null | 開始時に使ったセットアップテンプレートの名前 |
template.automation_template_name |
string | null | 開始時に使った自動化テンプレートの名前 |
reserved_at |
string | null | 予約した実行日時 |
executed_at |
string | null | 実行を始めた日時 |
completed_at |
string | null | 終了した日時(completed / failed / stopped / token_shortage のとき) |
created_at |
string | 実行を登録した日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
自動化が無い、または取得できる範囲外(Automation not found.) |
curl -X POST "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/stop");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"auto_unique": "Qw3eRt6yUi",
"mode": "blogmode",
"project": { "project_unique": "Pj8kL3mN2b", "project_name": "My Project" },
"content": { "variation_unique": "Ab3dEf6hIj9k", "title": "My blog title" },
"run_no": 1,
"status": "stopped",
"execution_mode": "sequential",
"phases": { "setup": "running", "step1": "not_started", "step2": "not_started", "step3": "not_started" },
"template": { "setup_template_name": null, "automation_template_name": "Morning blog" },
"reserved_at": "2030-01-02T03:04:05Z",
"executed_at": null,
"completed_at": "2026-10-21T10:05:00Z",
"created_at": "2026-10-21T10:00:00Z"
}
}
確認待ちを承認する
内容の確認待ち(status が waiting_confirmation)で止まっている自動化について、コンテンツの内容を確認済みにし、続き(SNS 用の文章の作成・投稿など)を実行します。画面で内容を確認したときと同じ操作です。成功すると自動化は pending に戻り、すぐに実行が始まります。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
auto_unique |
パス | string | 必須 | — | 自動化の実行のID |
Idempotency-Key |
ヘッダー | string | 任意 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
auto_unique |
string | 自動化の実行のID |
mode |
string | moviemode / blogmode / carouselmode |
project |
object | プロジェクト {project_unique, project_name} |
content.variation_unique |
string | コンテンツのID |
content.title |
string | null | タイトル(postmode はコンセプト名) |
run_no |
integer | そのコンテンツで何回目の実行か |
status |
string | 状態。pending(実行待ち。reserved_at が未来なら予約)/ executing(実行中)/ waiting_confirmation(内容の確認待ち。確認すると続きを実行)/ completed(完了)/ failed(失敗)/ stopped(停止)/ token_shortage(トークン不足で終了) |
execution_mode |
string | sequential(1件ずつ実行)/ parallel(同時に実行) |
phases |
object | 段階ごとの状態 {setup, step1, step2, step3}。not_started(未着手)/ running(実行中、または止まった段階)/ done(完了。スキップ、および completed した run では自動化の範囲外にした手順も含む)/ error(失敗) |
template.setup_template_name |
string | null | 開始時に使ったセットアップテンプレートの名前 |
template.automation_template_name |
string | null | 開始時に使った自動化テンプレートの名前 |
reserved_at |
string | null | 予約した実行日時 |
executed_at |
string | null | 実行を始めた日時 |
completed_at |
string | null | 終了した日時(completed / failed / stopped / token_shortage のとき) |
created_at |
string | 実行を登録した日時 |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 404 | not_found |
自動化が無い、または取得できる範囲外(Automation not found.) |
| 409 | automation_not_waiting_confirmation |
確認待ち(waiting_confirmation)ではない |
| 409 | content_readonly |
コンテンツがプランのダウングレードで閲覧専用 |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
| 503 | automation_dispatch_failed |
続きの実行の開始に失敗した。自動化は failed になります(コンテンツは確認済みのままなので、続きは新しく自動化を開始してください) |
curl -X POST "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \ -H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90"
import requests
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/automations/Qw3eRt6yUi/confirm");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"auto_unique": "Qw3eRt6yUi",
"mode": "carouselmode",
"project": { "project_unique": "Pj8kL3mN2b", "project_name": "My Project" },
"content": { "variation_unique": "Ab3dEf6hIj9k", "title": "My carousel title" },
"run_no": 1,
"status": "pending",
"execution_mode": "parallel",
"phases": { "setup": "done", "step1": "done", "step2": "done", "step3": "running" },
"template": { "setup_template_name": null, "automation_template_name": "Weekly carousel" },
"reserved_at": null,
"executed_at": "2026-10-21T09:00:00Z",
"completed_at": null,
"created_at": "2026-10-21T09:00:00Z"
}
}
投稿の確認
投稿(ポストモード)の自動化で、投稿前の確認をあり・任意にしたコンテンツの投稿を、承認・すぐ投稿・日時の変更・取り消しします。画面の確認待ちの一覧や確認メールのリンク先と同じ投稿が対象で、同じ規則で動きます。一覧はプランに関係なく使え、操作は Pro プラン以上で使えます。
-
確認待ちの投稿一覧
GET /post-confirms -
投稿を承認する
POST /post-schedules/{schedule_unique}/approve -
期限切れの投稿をすぐ投稿する
POST /post-schedules/{schedule_unique}/post-now -
期限切れの投稿の日時を変更する
PATCH /post-schedules/{schedule_unique} -
投稿を取り消す
DELETE /post-schedules/{schedule_unique}
確認待ちの投稿一覧
確認メールを送った投稿のうち、予定時刻の前(upcoming)と期限切れ(expired)のものを予定時刻の近い順に取得します。upcoming は承認待ち(awaiting。承認しないと投稿されない)と通知のみ(notice。そのまま投稿される)の投稿です。expired は承認されないまま予定時刻を過ぎて投稿されなかった投稿で、予定時刻から30日間だけ返します。スレッドは最初の投稿を1件として返し、2件目以降は thread に入ります。プランに関係なく使えます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
state |
クエリ | string | 任意 | — | upcoming(予定時刻の前)または expired(期限切れ)で絞り込みます。省略時は両方 |
project_unique |
クエリ | string | 任意 | — | このプロジェクトの投稿だけを返します |
page |
クエリ | integer | 任意 | 1 |
取得するページ(1から) |
per_page |
クエリ | integer | 任意 | 20 |
1ページの件数(1〜100) |
| 項目 | 型 | 説明 |
|---|---|---|
data[].schedule_unique |
string | 投稿の予定のID。操作のパスに使います |
data[].state |
string | null | upcoming(予定時刻の前)/ expired(期限切れ)。承認・日時の変更などで確認の対象でなくなった投稿は null(操作の応答だけ) |
data[].confirm_state |
string | awaiting(承認待ち。承認するまで投稿されない)/ notice(通知のみ。そのまま投稿される)/ confirmed(承認済み)/ none(確認なし) |
data[].confirm_mode |
string | コンテンツの確認の設定。required(承認するまで投稿しない)/ optional(承認しなくても投稿する)/ none(確認しない) |
data[].can_approve |
boolean | 承認できるか(upcoming で awaiting のとき true) |
data[].can_post_now |
boolean | すぐ投稿できるか(expired のとき true) |
data[].can_reschedule |
boolean | 日時を変更できるか(expired のとき true) |
data[].scheduled_at |
string | 投稿する予定日時 |
data[].scheduled_at_local |
string | 予定日時(timezone の現地時刻。YYYY-MM-DDTHH:MM:SS) |
data[].timezone |
string | 予定を作ったときのタイムゾーン |
data[].deadline_at |
string | null | 操作できる期限。upcoming は予定時刻(過ぎると expired)、expired は予定時刻の30日後(過ぎると一覧から消え、操作できない)。state が null なら null |
data[].project |
object | プロジェクト {project_unique, project_name} |
data[].concept |
object | コンセプト {concept_unique, concept_name} |
data[].variation_unique |
string | コンテンツのID |
data[].post_unique |
string | 投稿のID(投稿スケジュールの items[].post_unique と同じ) |
data[].post_type |
string | 投稿タイプ。assertion(主張)/ knowhow(ノウハウ)/ experience(体験)/ casual(日常) |
data[].text |
string | 投稿の本文(スレッドの最初の投稿) |
data[].thread[] |
object | スレッドの2件目以降の投稿 {text, image}(順番どおり。スレッドでなければ空の配列) |
data[].image |
object | null | 添付する画像 {url, expires_at}(署名付きURL。1時間で失効)。無ければ null |
meta.total |
integer | 条件に合う総件数 |
meta.current_page |
integer | 現在のページ |
meta.per_page |
integer | 1ページの件数 |
meta.last_page |
integer | 最後のページ |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
プロジェクトが無い、または取得できる範囲外(Project not found.) |
| 422 | validation_error |
パラメータが不正 |
curl "https://stepeee.com/public-api/v1/post-confirms?state=upcoming" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/post-confirms?state=upcoming",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/post-confirms?state=upcoming", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/post-confirms?state=upcoming")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/post-confirms?state=upcoming"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/post-confirms?state=upcoming");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"schedule_unique": "aB3dE5fG7hJ9",
"state": "upcoming",
"confirm_state": "awaiting",
"confirm_mode": "required",
"can_approve": true,
"can_post_now": false,
"can_reschedule": false,
"scheduled_at": "2026-10-19T13:00:00Z",
"scheduled_at_local": "2026-10-19T22:00:00",
"timezone": "Asia/Tokyo",
"deadline_at": "2026-10-19T13:00:00Z",
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My brand" },
"concept": { "concept_unique": "Cx2Yz4Wv6Ut8", "concept_name": "Morning tips" },
"variation_unique": "Vr5Ws7Xt9Yu1",
"post_unique": "Ps3Qt5Ru7Sv9",
"post_type": "knowhow",
"text": "First post of the thread",
"thread": [
{ "text": "Second post", "image": null },
{ "text": "Third post", "image": { "url": "https://...", "expires_at": "2026-10-19T13:00:00Z" } }
],
"image": null
}
],
"meta": { "total": 1, "current_page": 1, "per_page": 20, "last_page": 1 }
}
投稿を承認する
承認待ち(upcoming で confirm_state が awaiting)の投稿を承認します。承認した投稿は予定時刻に投稿されます。予定時刻を過ぎた投稿には、すぐ投稿か日時の変更を使ってください。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
schedule_unique |
パス | string | 必須 | — | 投稿の予定のID(GET /post-confirms の schedule_unique) |
Idempotency-Key |
ヘッダー | string | 任意 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
schedule_unique / state / … / image |
— | 確認待ちの投稿一覧の1件と同じ(操作のあとの状態) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 404 | post_schedule_not_found |
GET /post-confirms に出ない投稿(存在しない・取得できる範囲外・確認の対象でない・承認済み) |
| 409 | confirm_expired |
予定時刻を過ぎている(すぐ投稿か日時の変更を使う) |
| 409 | confirm_not_pending |
承認待ちではない(通知のみ notice の投稿など) |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
curl -X POST "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \ -H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90"
import requests
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/approve");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"schedule_unique": "aB3dE5fG7hJ9",
"state": null,
"confirm_state": "confirmed",
"confirm_mode": "required",
"can_approve": false,
"can_post_now": false,
"can_reschedule": false,
"scheduled_at": "2026-10-19T13:00:00Z",
"scheduled_at_local": "2026-10-19T22:00:00",
"timezone": "Asia/Tokyo",
"deadline_at": null,
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My brand" },
"concept": { "concept_unique": "Cx2Yz4Wv6Ut8", "concept_name": "Morning tips" },
"variation_unique": "Vr5Ws7Xt9Yu1",
"post_unique": "Ps3Qt5Ru7Sv9",
"post_type": "knowhow",
"text": "First post of the thread",
"thread": [
{ "text": "Second post", "image": null },
{ "text": "Third post", "image": { "url": "https://...", "expires_at": "2026-10-19T13:00:00Z" } }
],
"image": null
}
}
期限切れの投稿をすぐ投稿する
期限切れ(expired)の投稿を、いまから1分後の予定にして承認済みにします(まもなく投稿されます)。スレッドの2件目以降も同じだけ時刻をずらします。期限切れの投稿にだけ使えます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
schedule_unique |
パス | string | 必須 | — | 投稿の予定のID(GET /post-confirms の schedule_unique) |
allow_close_slot |
本文 | boolean | 任意 | false |
同じコンテンツの他の予約との間隔が最小間隔(90分)より短くなっても実行するなら true |
Idempotency-Key |
ヘッダー | string | 任意 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
schedule_unique / state / … / image |
— | 確認待ちの投稿一覧の1件と同じ(操作のあとの状態) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 403 | resource_readonly |
コンテンツがプランのダウングレードで閲覧専用 |
| 404 | post_schedule_not_found |
GET /post-confirms に出ない投稿(存在しない・取得できる範囲外・確認の対象でない・承認済み) |
| 409 | confirm_not_expired |
期限切れではない(予定時刻の前は承認を使う) |
| 409 | schedule_close_to_other_slot |
allow_close_slot が false で、同じコンテンツの他の予約との間隔が90分より短くなる。details に min_gap_minutes(最小間隔の分数)・timezone・conflicts(近い予約 {scheduled_at_local, minutes_apart} の配列) |
| 409 | schedule_locked |
投稿中・投稿済み、または予定時刻の前後2分以内で投稿の処理と重なる |
| 409 | schedule_processing |
投稿の処理と同時に操作され、変更できなかった |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | validation_error |
allow_close_slot が true / false ではない |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
curl -X POST "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90" \
-d '{
"allow_close_slot": true
}'
import requests
body = """{
"allow_close_slot": true
}"""
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
body: JSON.stringify({
"allow_close_slot": true
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
request.httpBody = """
{
"allow_close_slot": true
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"allow_close_slot": true
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"allow_close_slot": true
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9/post-now");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"schedule_unique": "aB3dE5fG7hJ9",
"state": null,
"confirm_state": "confirmed",
"confirm_mode": "required",
"can_approve": false,
"can_post_now": false,
"can_reschedule": false,
"scheduled_at": "2026-10-21T12:01:00Z",
"scheduled_at_local": "2026-10-21T21:01:00",
"timezone": "Asia/Tokyo",
"deadline_at": null,
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My brand" },
"concept": { "concept_unique": "Cx2Yz4Wv6Ut8", "concept_name": "Morning tips" },
"variation_unique": "Vr5Ws7Xt9Yu1",
"post_unique": "Ps3Qt5Ru7Sv9",
"post_type": "knowhow",
"text": "First post of the thread",
"thread": [
{ "text": "Second post", "image": null },
{ "text": "Third post", "image": { "url": "https://...", "expires_at": "2026-10-19T13:00:00Z" } }
],
"image": null
}
}
期限切れの投稿の日時を変更する
期限切れ(expired)の投稿の予定日時を変更して承認済みにします(指定した日時に投稿されます)。スレッドの2件目以降も同じだけ時刻をずらします。日時を変更できるのは期限切れの投稿だけです。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
schedule_unique |
パス | string | 必須 | — | 投稿の予定のID(GET /post-confirms の schedule_unique) |
scheduled_at |
本文 | string | 必須 | — | 新しい予定日時(未来の日時)。時差つきの ISO 8601 で指定します(2026-10-21T09:30:00+09:00、2026-10-21T00:30:00Z など。秒は省略でき、秒未満は切り捨て)。投稿の timezone の時刻に直して保存します |
allow_close_slot |
本文 | boolean | 任意 | false |
同じコンテンツの他の予約との間隔が最小間隔(90分)より短くなっても実行するなら true |
| 項目 | 型 | 説明 |
|---|---|---|
schedule_unique / state / … / image |
— | 確認待ちの投稿一覧の1件と同じ(操作のあとの状態) |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 403 | resource_readonly |
コンテンツがプランのダウングレードで閲覧専用 |
| 404 | post_schedule_not_found |
GET /post-confirms に出ない投稿(存在しない・取得できる範囲外・確認の対象でない・承認済み) |
| 409 | confirm_not_expired |
期限切れではない(予定時刻の前は承認を使う) |
| 409 | schedule_close_to_other_slot |
allow_close_slot が false で、同じコンテンツの他の予約との間隔が90分より短くなる。details に min_gap_minutes(最小間隔の分数)・timezone・conflicts(近い予約 {scheduled_at_local, minutes_apart} の配列) |
| 409 | schedule_locked |
投稿中・投稿済み、または予定時刻の前後2分以内で投稿の処理と重なる |
| 409 | schedule_processing |
投稿の処理と同時に操作され、変更できなかった |
| 422 | confirm_reschedule_past |
scheduled_at が現在以前 |
| 422 | validation_error |
scheduled_at が無い・時差が無い・日時として読めない、または allow_close_slot が true / false ではない |
curl -X PATCH "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}'
import requests
body = """{
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}"""
response = requests.request(
"PATCH",
"https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9", {
method: "PATCH",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9")!)
request.httpMethod = "PATCH"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = """
{
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString("""
{
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"scheduled_at": "2026-10-22T09:30:00-05:00",
"allow_close_slot": false
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"schedule_unique": "aB3dE5fG7hJ9",
"state": null,
"confirm_state": "confirmed",
"confirm_mode": "required",
"can_approve": false,
"can_post_now": false,
"can_reschedule": false,
"scheduled_at": "2026-10-22T14:30:00Z",
"scheduled_at_local": "2026-10-22T23:30:00",
"timezone": "Asia/Tokyo",
"deadline_at": null,
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My brand" },
"concept": { "concept_unique": "Cx2Yz4Wv6Ut8", "concept_name": "Morning tips" },
"variation_unique": "Vr5Ws7Xt9Yu1",
"post_unique": "Ps3Qt5Ru7Sv9",
"post_type": "knowhow",
"text": "First post of the thread",
"thread": [
{ "text": "Second post", "image": null },
{ "text": "Third post", "image": { "url": "https://...", "expires_at": "2026-10-19T13:00:00Z" } }
],
"image": null
}
}
投稿を取り消す
投稿を取り消します(予定時刻の前でも、期限切れでも)。投稿・スレッドの2件目以降・予約をまとめて削除します。元に戻せません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
schedule_unique |
パス | string | 必須 | — | 投稿の予定のID(GET /post-confirms の schedule_unique) |
| 項目 | 型 | 説明 |
|---|---|---|
schedule_unique |
string | 取り消した投稿の予定のID |
deleted |
boolean | 常に true |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 403 | resource_readonly |
コンテンツがプランのダウングレードで閲覧専用 |
| 404 | post_schedule_not_found |
GET /post-confirms に出ない投稿(存在しない・取得できる範囲外・確認の対象でない・承認済み) |
| 409 | post_posting_locked |
投稿中(スレッドの2件目以降を含む)で取り消せない |
curl -X DELETE "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.request(
"DELETE",
"https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9", {
method: "DELETE",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9")!)
request.httpMethod = "DELETE"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/post-schedules/aB3dE5fG7hJ9");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"schedule_unique": "aB3dE5fG7hJ9",
"deleted": true
}
}
Webhook
登録した URL へ、自動化や投稿の出来事を JSON で送ります。完了・失敗・確認待ちを、APIを繰り返し呼ばずに知りたいときに使います。登録と送信テストは Pro プラン以上、一覧と削除はプランに関係なく使えます。
-
通知先一覧
GET /webhooks -
通知先を登録する
POST /webhooks -
通知先を削除する
DELETE /webhooks/{webhook_unique} -
送信をテストする
POST /webhooks/{webhook_unique}/test
通知先一覧
登録した通知先を登録順に取得します(最大5件。ページングはありません)。署名用のシークレットは含みません。プランに関係なく使えます。
| 項目 | 型 | 説明 |
|---|---|---|
data[].webhook_unique |
string | 通知先のID |
data[].url |
string | 送信先の URL |
data[].events |
string[] | 受け取るイベント名 |
data[].description |
string | null | メモ |
data[].is_active |
boolean | いまイベントを送る状態か。持ち主が Pro プラン以上(チームのメンバーはチームのオーナーが Team プラン)のとき true。false のあいだに起きた出来事は送りません |
data[].last_delivery_at |
string | null | 直近の送信を試みた日時(送信テストは含みません) |
data[].last_delivery_status |
string | null | 直近の送信の結果。succeeded(成功)/ failed(失敗)。まだ送っていなければ null |
data[].last_response_status |
integer | null | 直近の送信で受け取った HTTP ステータス(応答が無ければ null) |
data[].last_error |
string | null | 直近の送信が失敗した理由。値は送信テストの error と同じ |
data[].created_at |
string | 作成日時 |
curl "https://stepeee.com/public-api/v1/webhooks" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.get(
"https://stepeee.com/public-api/v1/webhooks",
headers={"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx"},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/webhooks", {
headers: { Authorization: "Bearer sk_xxxxxxxxxxxxxxxx" },
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/webhooks")!)
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/webhooks"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/webhooks");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": [
{
"webhook_unique": "Xk3pQ9vLm2Ta",
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook",
"is_active": true,
"last_delivery_at": "2026-10-21T12:01:00Z",
"last_delivery_status": "failed",
"last_response_status": 503,
"last_error": "non_2xx_response",
"created_at": "2026-10-20T09:00:00Z"
}
]
}
通知先を登録する
通知先を登録します。応答の secret(署名用のシークレット)はこの応答でだけ返し、あとから表示する方法はありません。失くした場合は、通知先を削除して登録し直してください。登録できるのは5件までです。登録する前に起きた出来事は送りません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
url |
本文 | string | 必須 | — | 送信先の URL(https のみ、ポートは 443 のみ(省略可)、2048文字以内)。ユーザー名・パスワードを含む URL は登録できません。内部・予約済みのアドレス(プライベート IP・ループバック・リンクローカル・localhost など)に解決される URL と、名前解決できない URL は登録できません |
events |
本文 | string[] | 必須 | — | 受け取るイベント名(イベントの一覧から1件以上、重複不可) |
description |
本文 | string | null | 任意 | — | メモ(100文字以内) |
Idempotency-Key |
ヘッダー | string | 任意 | — | 操作ごとに作った一意な文字列(1〜255文字の表示可能な ASCII)。同じキーで同じ内容を再送すると、最初の応答をそのまま返します(共通仕様の Idempotency-Key を参照) |
| 項目 | 型 | 説明 |
|---|---|---|
webhook_unique |
string | 通知先のID |
url |
string | 送信先の URL |
events |
string[] | 受け取るイベント名 |
description |
string | null | メモ |
is_active |
boolean | いまイベントを送る状態か。持ち主が Pro プラン以上(チームのメンバーはチームのオーナーが Team プラン)のとき true。false のあいだに起きた出来事は送りません |
last_delivery_at |
string | null | 直近の送信を試みた日時(送信テストは含みません) |
last_delivery_status |
string | null | 直近の送信の結果。succeeded(成功)/ failed(失敗)。まだ送っていなければ null |
last_response_status |
integer | null | 直近の送信で受け取った HTTP ステータス(応答が無ければ null) |
last_error |
string | null | 直近の送信が失敗した理由。値は送信テストの error と同じ |
created_at |
string | 作成日時 |
secret |
string | 署名用のシークレット(whsec_ で始まる)。この応答でだけ返します |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 409 | webhook_limit_reached |
すでに5件登録している |
| 409 | idempotency_request_in_progress |
同じ Idempotency-Key のリクエストがまだ処理中 |
| 422 | validation_error |
入力が不正(https ではない URL、443 以外のポート、ユーザー名・パスワードを含む URL、内部のアドレスに解決される・名前解決できない URL、知らないイベント名、イベント名の重複など) |
| 422 | idempotency_key_invalid |
Idempotency-Key が1〜255文字の表示可能な ASCII ではない |
| 422 | idempotency_key_reused |
同じ Idempotency-Key を別の内容のリクエストに使った |
curl -X POST "https://stepeee.com/public-api/v1/webhooks" \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90" \
-d '{
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}'
import requests
body = """{
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}"""
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/webhooks",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
data=body,
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/webhooks", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
},
body: JSON.stringify({
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}),
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/webhooks")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90", forHTTPHeaderField: "Idempotency-Key")
request.httpBody = """
{
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}
""".data(using: .utf8)
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/webhooks"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}
"""))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$body = <<<'JSON'
{
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook"
}
JSON;
$ch = curl_init("https://stepeee.com/public-api/v1/webhooks");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
"Content-Type: application/json",
"Idempotency-Key: 5f0c2d8e-7a41-4c1b-9d3e-2b8f6a1c4e90",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"webhook_unique": "Xk3pQ9vLm2Ta",
"url": "https://example.com/hooks/stepeee",
"events": ["automation.completed", "post.published"],
"description": "production hook",
"is_active": true,
"last_delivery_at": null,
"last_delivery_status": null,
"last_response_status": null,
"last_error": null,
"created_at": "2026-10-21T12:00:00Z",
"secret": "whsec_5f0c2a9e8b7d4c3a1f6e9d8c7b6a5f4e3d2c1b0a9f8e7d6c"
}
}
通知先を削除する
通知先を削除します。まだ送っていないイベントと再試行待ちのイベントも送りません。プランに関係なく使えます。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
webhook_unique |
パス | string | 必須 | — | 通知先のID |
| 項目 | 型 | 説明 |
|---|---|---|
webhook_unique |
string | 削除した通知先のID |
deleted |
boolean | 常に true |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 404 | not_found |
通知先が無い、または他のユーザーの通知先 |
curl -X DELETE "https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.request(
"DELETE",
"https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta", {
method: "DELETE",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta")!)
request.httpMethod = "DELETE"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"webhook_unique": "Xk3pQ9vLm2Ta",
"deleted": true
}
}
送信をテストする
webhook.test イベントをその場で1回送り、結果を返します。本番と同じ署名・ヘッダー・送信先の検査で送るので、受け取る側の署名の検証を確かめるときに使えます。再試行はせず、last_delivery_at などにも記録しません。
| 名前 | 場所 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|---|
webhook_unique |
パス | string | 必須 | — | 通知先のID |
| 項目 | 型 | 説明 |
|---|---|---|
delivered |
boolean | 2xx の応答を受け取ったか |
response_status |
integer | null | 受け取った HTTP ステータス(応答が無ければ null) |
error |
string | null | 失敗の理由。url_blocked(https ではない・443 以外のポート・ユーザー名とパスワードを含む、または送信の直前に内部のアドレスに解決された・名前解決できなかった)/ timeout(5秒以内に応答が無かった)/ connection_failed(接続・TLS に失敗した)/ non_2xx_response(2xx 以外の応答。リダイレクトも失敗として扱い、追いません)。成功したときは null |
| ステータス | コード | 発生する条件 |
|---|---|---|
| 403 | plan_required |
APIキーの持ち主が Pro プラン未満 |
| 403 | team_plan_lost |
チームのメンバーで、チームのオーナーが Team プランでなくなった |
| 404 | not_found |
通知先が無い、または他のユーザーの通知先 |
curl -X POST "https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test" \ -H "Authorization: Bearer sk_xxxxxxxxxxxxxxxx"
import requests
response = requests.request(
"POST",
"https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test",
headers={
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
)
print(response.json())
const response = await fetch("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test", {
method: "POST",
headers: {
"Authorization": "Bearer sk_xxxxxxxxxxxxxxxx",
},
});
const data = await response.json();
console.log(data);
var request = URLRequest(url: URL(string: "https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test")!)
request.httpMethod = "POST"
request.setValue("Bearer sk_xxxxxxxxxxxxxxxx", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test"))
.header("Authorization", "Bearer sk_xxxxxxxxxxxxxxxx")
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
$ch = curl_init("https://stepeee.com/public-api/v1/webhooks/Xk3pQ9vLm2Ta/test");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer sk_xxxxxxxxxxxxxxxx",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
{
"data": {
"delivered": false,
"response_status": 500,
"error": "non_2xx_response"
}
}
イベント
通知先に登録したイベントが起きると、登録した URL へ POST します。送るのは、通知先の持ち主がその時点で取得できるプロジェクトの出来事だけです。出来事は1分ごとに確かめるため、届くまで数分かかることがあります。通知先を登録する前の出来事と、持ち主が Pro プラン未満のあいだ(チームのメンバーはチームのオーナーが Team プランでないあいだ)の出来事は送りません。
| イベント | 意味 |
|---|---|
automation.waiting_confirmation | 自動化(動画・ブログ・カルーセル)が内容の確認待ちで止まった |
automation.completed | 自動化が最後まで完了した |
automation.failed | 自動化が失敗(failed)・停止(stopped)・トークン不足(token_shortage)で終わった |
post.published | SNS へ投稿した(動画・ブログ・カルーセルの投稿結果が success になった、投稿(ポストモード)を X に投稿した)。手動の投稿も自動化の投稿も対象です |
post.failed | 投稿に失敗した(動画・ブログ・カルーセルの投稿結果が failed・partial_success になった、投稿(ポストモード)が投稿や本文の作成に失敗して見送られた) |
post.confirm_required | 投稿(ポストモード)の承認待ちの投稿が GET /post-confirms に出た(承認するまで投稿されない) |
webhook.test | 送信テスト(POST /webhooks/{webhook_unique}/test)。通知先に登録するイベントには使えません |
送信する本文
本文は {id, type, created_at, data} の JSON(UTF-8)です。id はイベントのID(evt_ で始まる)、type はイベント名、created_at はイベントを記録した日時です。同じイベントを再送するときは本文は同じで、署名の t だけが変わります。data の形はイベントごとに次のとおりです。
| イベント | data の形 |
|---|---|
automation.* | GET /automations の data[] の1件と同じ形。status は automation.waiting_confirmation が waiting_confirmation、automation.completed が completed、automation.failed が failed / stopped / token_shortage |
post.publishedpost.failed | 動画・ブログ・カルーセル: GET /projects/{project_unique}/publications の data[] の1件に project を加えた形。post.failed の status は failed または partial_success で、error_code に投稿結果と同じ失敗のコードが入ります。投稿(ポストモード): 同じ形に schedule_unique を加えたもの。publication_unique は投稿のID(本文の作成に失敗した予定では null)、content.title はコンセプト名、account は null、error_code は token_expired / api_error / not_found / insufficient_token / no_x_account / node_ws_timeout です。is_automation で自動化の投稿かどうかを区別できます |
post.confirm_required | GET /post-confirms の data[] の1件と同じ形で、イベントを記録した時点の値です。通知のみ(notice)の投稿では送りません。image の署名付きURLは記録から1時間で失効するので、遅れて届いた場合は GET /post-confirms で取り直してください。同じ予定の投稿が作り直されると、新しい post_unique で再び届きます |
webhook.test | {"webhook_unique": "…"} |
本文の例
automation.failed{
"id": "evt_Q2x8Lr0aZk9MvB3pT7cYw1Nd",
"type": "automation.failed",
"created_at": "2026-10-21T12:01:03Z",
"data": {
"auto_unique": "a8Kd02LmQz",
"mode": "blogmode",
"project": { "project_unique": "Pj7Xc2Lq9W", "project_name": "My Project" },
"content": { "variation_unique": "Vb3Nq8Ls1Kd0", "title": "How to start" },
"run_no": 2,
"status": "token_shortage",
"execution_mode": "sequential",
"phases": { "setup": "done", "step1": "done", "step2": "running", "step3": "not_started" },
"template": { "setup_template_name": "Default", "automation_template_name": null },
"reserved_at": null,
"executed_at": "2026-10-21T11:40:00Z",
"completed_at": "2026-10-21T12:00:41Z",
"created_at": "2026-10-21T11:39:58Z"
}
}
post.published{
"id": "evt_7hT2mWq9Zp3LxR8cVb1Nk5Ds",
"type": "post.published",
"created_at": "2026-10-21T12:02:10Z",
"data": {
"publication_unique": "Lg4Hs9Pq2Wx7",
"mode": "moviemode",
"project": { "project_unique": "Pj7Xc2Lq9W", "project_name": "My Project" },
"content": { "variation_unique": "Mv8Kq2Zt5Rb1", "title": "5 tips" },
"platform": "youtube",
"account": { "account_unique": "Ac1Bd2Ef3Gh4", "name": "My Channel" },
"status": "success",
"post_url": "https://www.youtube.com/watch?v=xxxxxxxx",
"error_code": null,
"is_automation": true,
"posted_at": "2026-10-21T12:01:55Z",
"created_at": "2026-10-21T12:01:20Z"
}
}
post.failed{
"id": "evt_9Zq1Lm4Xc7Vb2Nk8Ds3Pt6Wr",
"type": "post.failed",
"created_at": "2026-10-21T09:00:40Z",
"data": {
"publication_unique": "Pp5Kd8Lw2Qz9",
"mode": "postmode",
"project": { "project_unique": "Pj7Xc2Lq9W", "project_name": "My Project" },
"content": { "variation_unique": "Pv4Lk9Qz2Wx6", "title": "My X concept" },
"platform": "x",
"account": null,
"status": "failed",
"post_url": null,
"error_code": "token_expired",
"is_automation": true,
"posted_at": null,
"created_at": "2026-10-20T21:00:12Z",
"schedule_unique": "Sc6Hj1Kl8Mn3"
}
}
post.confirm_required{
"id": "evt_3Kd8Lq2Wz7Xc1Vb9Nm4Pt6Rs",
"type": "post.confirm_required",
"created_at": "2026-10-19T08:15:02Z",
"data": {
"schedule_unique": "aB3dE5fG7hJ9",
"state": "upcoming",
"confirm_state": "awaiting",
"confirm_mode": "required",
"can_approve": true,
"can_post_now": false,
"can_reschedule": false,
"scheduled_at": "2026-10-19T13:00:00Z",
"scheduled_at_local": "2026-10-19T22:00:00",
"timezone": "Asia/Tokyo",
"deadline_at": "2026-10-19T13:00:00Z",
"project": { "project_unique": "Pq7Rs9Tu1V", "project_name": "My brand" },
"concept": { "concept_unique": "Cx2Yz4Wv6Ut8", "concept_name": "Morning tips" },
"variation_unique": "Vr5Ws7Xt9Yu1",
"post_unique": "Ps3Qt5Ru7Sv9",
"post_type": "knowhow",
"text": "First post of the thread",
"thread": [
{ "text": "Second post", "image": null }
],
"image": { "url": "https://...", "expires_at": "2026-10-19T09:15:02Z" }
}
}
webhook.test{
"id": "evt_Q2x8Lr0aZk9MvB3pT7cYw1Nd",
"type": "webhook.test",
"created_at": "2026-10-21T12:00:00Z",
"data": { "webhook_unique": "Xk3pQ9vLm2Ta" }
}
送信するヘッダー
| ヘッダー | 説明 |
|---|---|
Content-Type: application/json | 本文の形式 |
Stepeee-Signature: t=1792584000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd | 署名。t は送信した時刻(UNIX 秒)、v1 は署名(HMAC-SHA256 の16進)です。検証の方法は下の署名の検証を見てください |
Stepeee-Event-Id: evt_Q2x8Lr0aZk9MvB3pT7cYw1Nd | イベントのID(本文の id と同じ)。再送でも変わらないので、重複を除くのに使います |
Stepeee-Event-Type: automation.failed | イベント名(本文の type と同じ) |
User-Agent: Stepeee-Webhooks/1.0 | 送信元 |
署名の検証
受け取った本文が Stepeee から送られ、書き換えられていないことを確かめるため、次の手順で署名を検証してください。
- Stepeee-Signature ヘッダーを「,」で区切り、t= の値(UNIX 秒)と v1= の値(16進64文字)を取り出します。
- 受け取った本文をバイト列のまま使い(JSON を読み込んで作り直さない)、t の値・「.」・本文をつなげた文字列を作ります。
- 登録したときに受け取った secret(whsec_ を含む全体)を鍵にして HMAC-SHA256 を計算し、小文字の16進にします。
- 計算した値と v1 を、かかる時間が内容によって変わらない比較(Python の hmac.compare_digest、PHP の hash_equals など)で比べます。一致しなければ 400 などを返し、処理しません。
- 古いリクエストの再送を防ぐため、t が現在時刻から5分以上ずれていたら拒否することをおすすめします。
- 本文の id で、すでに処理したイベントを除きます。
検証のコード例
import hmac, hashlib, time
def verify(body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, v1 = parts.get("t"), parts.get("v1")
if not t or not v1 or abs(time.time() - int(t)) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)
# Flask: verify(request.get_data(), request.headers["Stepeee-Signature"], SECRET)
const crypto = require("crypto");
function verify(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
const t = parts.t, v1 = parts.v1;
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > toleranceSec) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.`).update(rawBody).digest("hex");
return v1.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
// Express: receive the body as raw bytes with express.raw()
app.post("/hooks/stepeee", express.raw({ type: "application/json" }), (req, res) => {
if (!verify(req.body, req.get("Stepeee-Signature"), process.env.STEPEEE_WEBHOOK_SECRET)) return res.sendStatus(400);
const event = JSON.parse(req.body.toString("utf8"));
res.sendStatus(200);
});
function verifyStepeeeSignature(string $body, string $header, string $secret, int $tolerance = 300): bool
{
$parts = [];
foreach (explode(',', $header) as $part) {
[$k, $v] = array_pad(explode('=', $part, 2), 2, '');
$parts[$k] = $v;
}
if (! isset($parts['t'], $parts['v1']) || abs(time() - (int) $parts['t']) > $tolerance) {
return false;
}
$expected = hash_hmac('sha256', $parts['t'].'.'.$body, $secret);
return hash_equals($expected, $parts['v1']);
}
$ok = verifyStepeeeSignature(file_get_contents('php://input'), $_SERVER['HTTP_STEPEEE_SIGNATURE'] ?? '', $secret);
# BODY: raw request body, T: t from Stepeee-Signature, SECRET: whsec_...
printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}'
# The signature is valid if the output equals v1
成功の条件と再試行
5秒以内に 2xx を返すと、届いたものとして扱います。応答の本文は読まず、リダイレクトは追いません。2xx 以外の応答・タイムアウト・接続の失敗は再試行し、最初の送信を含めて最大8回送ります。次に送るまでの間隔は 1分 → 5分 → 30分 → 2時間 → 4時間 → 6時間 → 10時間 で、8回とも失敗したらそのイベントは送りません。送る時点で持ち主が Pro プラン未満(チームのメンバーはチームのオーナーが Team プランでない)なら、そのイベントは送りません。送る時点で持ち主がそのプロジェクトにアクセスできなくなっている(チームから外れた・権限を外された・プロジェクトが削除された)場合も送りません。
2xx を受け取るまで同じイベントを再送するため、同じイベントが2回以上届くことがあります。Stepeee-Event-Id(本文の id)で重複を除いてください。届く順番は保証しません。重い処理は 2xx を返したあとで行ってください。
送信先の条件
送信先は https の URL だけで、ポートは 443 に限ります。ユーザー名・パスワードを含む URL も登録できません。内部・予約済みのアドレス(プライベート IP・ループバック・リンクローカル・localhost など)に解決される URL と、名前解決できない URL は登録できません。送る直前にも名前を解決して確かめ、内部のアドレスに解決された場合は送らずに url_blocked として失敗にします。