このページの内容

開発者ドキュメント / REST API

自動化の仕事を、ひとつの会話へ。

メッセージの送信から返信、承認された業務の結果まで。Pushyou REST APIでつなぎましょう。

自分の接続を設定

01はじめる前に

招待されたPushyou内部テストアプリでアカウントと会話を作成してください。WebログインにはアプリでのQR承認が必要です。接続設定で会話を選び、実際の配信を確認できます。

設定 → 接続管理でプログラムごとの接続を作成し、必要な会話と操作のみを許可してください。キーは発行時に一度だけ表示されます。選択した会話への権限では新しい会話を作成できません。すべての会話へのアクセスとconversations:writeが必要です。

02認証

コンピューターまたはサーバーのBashかzshで実行します。キーは実行環境のシークレット設定に保存し、ブラウザーのコード、URL、公開する会話画面に含めないでください。MCP OAuthトークンはREST認証には使えません。

本番エンドポイント
export PUSHYOU_API_URL='https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouApi'
export PUSHYOU_MEDIA_URL='https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouMedia'
プログラムキーを読み込む
printf 'Pushyou API key: ' >&2
IFS= read -r -s PUSHYOU_API_KEY
printf '\n' >&2
export PUSHYOU_API_KEY
アカウントと権限の確認
curl --fail-with-body --silent --show-error \
  -X GET "$PUSHYOU_API_URL/v1/me" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY"

03最初のメッセージを送信

既存の会話を選択

アカウント応答のid、permissions、conversation_idsを確認します。conversation_idsがnullなら全会話へのアクセスです。許可された会話を取得し、YOUR_CONVERSATION_IDを実際のIDに置き換えてください。一覧取得にはconversations:readが必要です。

既存の会話を選択
curl --fail-with-body --silent --show-error \
  -X GET "$PUSHYOU_API_URL/v1/conversations?limit=20" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY"
PUSHYOU_CONVERSATION_ID
export PUSHYOU_CONVERSATION_ID='YOUR_CONVERSATION_ID'
メッセージを送信
curl --fail-with-body --silent --show-error \
  -X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/messages" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"id":"docs-message-01","text":"Pushyou connection verified.","notify":true}'
応答例 · HTTP 201
{
  "conversation_id": "YOUR_CONVERSATION_ID",
  "message_id": "docs-message-01",
  "duplicate": false
}

同じメッセージには同じIDを使います。同じIDと内容で再送するとHTTP 200とduplicate: trueが返ります。同じIDで異なる内容は409です。新しいメッセージには新しいIDを使ってください。

メッセージのフィールド

フィールド仕様
id必須。英数字、アンダースコア、ハイフンで1〜80文字。
text最大8,000文字。空でないテキストまたは添付ファイルが必要です。
attachment_ids同じ会話にアップロード済みのファイルIDを最大4件指定します。
card任意。report、actions、htmlカード。カードだけではテキストや添付の代わりになりません。
notify真偽値、初期値true。プッシュ通知を要求します。実際の配信には端末の許可と通知設定も影響します。

会話、メッセージ、履歴の一覧はlimit(1〜100、初期値50)とbefore=next_cursorを使います。フィルターを維持し、next_cursorがnullなら終了します。イベントは数値のafterカーソルで昇順に取得します。APIでの取得はアプリの既読処理とは別です。

04返信と業務の実行

アプリで返信してからイベントを取得します。通常の返信や操作を実際に処理した後、結果の保存、ACK、next_cursorの永続保存の順に進めます。ACKはイベント削除や排他的な実行権ではありません。通常の自動応答は会話ごとに1つのプログラムにするか、独自に調整してください。

返信を取得
curl --fail-with-body --silent --show-error \
  -X GET "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/events?after=0" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY"
ACK · YOUR_EVENT_ID
curl --fail-with-body --silent --show-error \
  -X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/events/YOUR_EVENT_ID/ack" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{}'

承認を依頼

承認を依頼
curl --fail-with-body --silent --show-error \
  -X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/tasks" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"id":"docs-report-01","title":"Review the weekly report","category_id":"reports","fields":[{"id":"notes","label":"Review notes","type":"multiline","required":false}]}'

タスクは承認と実行結果をまとめて追跡します。所有者の承認後、ワーカーはtask_protocol=1でイベントを取得し、実行トークンを永続保存してから試行を取得します。heartbeatで権利を維持し、実際の結果を保存してcompleteを送ります。完了時にイベントもACKされます。単独のACKでは未完了タスクを終了できません。

タスクのフィールド・実行権・結果仕様(英語)

Response receiver

継続的な返信にはRESTプログラムキーでNode 22以降のレシーバーを実行します。送信とACKの前に結果を保存します。プロセスの継続実行が必要で、PCのスリープ中は動きません。Codexモードは専用セッションを開始し、既存のチャットには接続しません。

Webhooks

署名付きの応答Webhookも利用できます。モバイルアプリの応答Webhook設定で接続してください。元の本文の署名を検証し、配信IDで重複を除きます。HTTP 2xxは受信確認であり、タスク完了ではありません。署名と再試行の仕様は業務ガイドにあります。

05ファイルと会話の画面

ファイルは専用のメディアエンドポイントと、media:writeまたはmedia:read権限のRESTキーを使います。元のバイト列をアップロードし、同じ会話のメッセージにファイルIDを添付します。ファイルURLは非公開で認証が必要です。画像は10 MiB、動画は25 MiBまでです。

ローカルのPNGをアップロードして添付
curl --fail-with-body --silent --show-error \
  "$PUSHYOU_MEDIA_URL/v1/media/docs-image-01?conversation_id=$PUSHYOU_CONVERSATION_ID" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY" \
  -H 'Content-Type: application/octet-stream' \
  -H 'X-Pushyou-Filename: review.png' \
  --data-binary @review.png
メッセージを送信
curl --fail-with-body --silent --show-error \
  -X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/messages" \
  -H "Authorization: Bearer $PUSHYOU_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"id":"docs-attachment-01","text":"Please review this image.","attachment_ids":["docs-image-01"]}'

MCPではpushyou_prepare_media_uploadにmedia_id、filename、content_type、バイト数、SHA-256を渡します。返されたupload.urlと専用ヘッダーをそのまま使い、5分以内に元のバイト列をPOSTしてからattachment_idsを送信します。RESTにも同じ準備APIがあります。アップロード権限をアカウントキーやMCP OAuthトークンに置き換えないでください。

PATCH …/viewに{"view": CARD}を送り、レポート、操作ボタン、HTML画面を公開できます。{"view": null}で削除します。画面は所有する会話から開きます。HTMLは外部通信、アプリの認証情報、ブラウザーの保存領域にアクセスできません。宣言した操作は同じ会話のイベントになります。

Card / Field
リクエスト形式
Card =
  { type: "report", title: string, items: { title: string, body?: string, label?: string }[] }
| { type: "actions", title: string, body?: string, actions: { id: ID, label: string }[] }
| { type: "html", title: string, html: string, height?: integer, actions?: { id: ID, label: string }[] }

Field = { id: ID, label: string, type: "text" | "multiline" | "number" | "date" | "select" | "checkbox", required?: boolean, options?: string[], min?: number, max?: number }

06エンドポイント一覧

各グループのベースURLにパスを追加します。ファイル専用のアップロード権限を使う場合以外はBearerプログラムキーが必要です。項目を開いてリクエスト形式を確認し、例のIDを置き換えてください。

JSON API

https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouApi
POST/v1/conversations/{id}/media/uploads

ファイルのアップロードを準備

ファイルID・名前・形式・バイト数・SHA-256を指定すると、5分間有効なファイル専用の送信権限を取得できます。media:writeが必要です。

リクエスト形式
{ media_id: ID, filename: string, content_type: string, size: integer, sha256: string }
GET/v1/me

アカウントを確認

このAPIキーに紐づくアカウントと権限を確認します。

リクエスト形式
GET /v1/me
→ { id, key_scope, permissions, conversation_ids }
POST/v1/conversations

会話を作成

idとnameで会話を作成します。同じID・内容で再試行しても重複作成されません。

リクエスト形式
{ id: ID, name: string, description?: string, kind?: string, view?: Card }
GET/v1/conversations

会話の一覧

アカウントの会話一覧を取得します。

リクエスト形式
?limit=20&before=CURSOR
→ { conversations, next_cursor }
GET/v1/conversations/{id}

会話を取得

会話の名前・説明・状態・公開ビューを取得します。

リクエスト形式
GET /v1/conversations/ROOM_ID
→ { conversation }
PATCH/v1/conversations/{id}

会話を更新

名前・説明・固定状態を更新します。activeで会話を一時停止・再開できます。

リクエスト形式
{ name?: string, description?: string, pinned?: boolean, active?: boolean, view?: Card | null }
POST/v1/conversations/{id}/messages

メッセージを送信

テキスト・カード・添付を送信します。送信済みファイルのIDをattachment_idsに指定し、notifyで通知を制御します。

リクエスト形式
{ id: ID, text?: string, attachment_ids?: ID[], card?: Card | null, notify?: boolean }
GET/v1/conversations/{id}/messages

会話を読む

受信メッセージとユーザーの返信を新しい順に取得します。

リクエスト形式
?limit=20&before=CURSOR
→ { messages, next_cursor }
GET/v1/conversations/{id}/messages/{message_id}

メッセージを取得

メッセージ1件の内容とカードを読みます。

リクエスト形式
GET /v1/conversations/ROOM_ID/messages/MESSAGE_ID
→ { message }
GET/v1/conversations/{id}/events/head

現在の応答番号

新しい受信プログラムを始める前に最新の番号を取得します。既読や処理済みの状態は変えません。

リクエスト形式
GET /v1/conversations/ROOM_ID/events/head
→ { cursor }
GET/v1/conversations/{id}/receiver-status

受信プログラムの状態を取得

最後に報告された受信状態と時刻を確認します。タスクの完了や実行権の取得を確認するものではありません。

リクエスト形式
GET /v1/conversations/ROOM_ID/receiver-status
→ { receivers, checked_at }
PUT/v1/conversations/{id}/receiver-status/{instance_id}

受信プログラムの状態を報告

実行ごとに新しいUUIDと増加するsequenceで報告します。会話の読み取り・イベントの読み取り・ACK・メッセージの書き込み権限が必要です。

リクエスト形式
{ sequence: positive_integer, state: "starting" | "receiving" | "processing" | "retrying" | "paused" | "stopped" | "needs_review" | "delivery_pending" }
instance_id: UUID v4
GET/v1/conversations/{id}/events

ユーザーの応答を取得

指定した番号以降の返信と送信済みボタン操作を取得します。

リクエスト形式
?after=0
?after=0&task_protocol=1
→ { events, next_cursor }
POST/v1/conversations/{id}/events/{event_id}/ack

応答の処理を確認

エージェントやサーバーが処理したイベントを処理済みにします。

リクエスト形式
{}
→ { ok: true }
GET/v1/conversations/{id}/view

会話ビューを取得

会話に公開されたHTML・コンポーネントビューを読みます。

リクエスト形式
GET /v1/conversations/ROOM_ID/view
→ { view: Card | null }
PATCH/v1/conversations/{id}/view

会話ビューを公開

viewにカードを送ると、会話の上部にビューを開く操作が追加されます。nullで削除します。

リクエスト形式
{ view: Card | null }
GET/v1/history

履歴を取得

category_id・kind・status_group・conversation_idを組み合わせて履歴をページ単位で取得します。

リクエスト形式
?limit=20&before=CURSOR
&category_id=reports&conversation_id=ROOM_ID
&kind=received&status_group=attention
&result_pending=true
kind: received | action | saved
status_group: attention | progress | problems | complete
→ { history, next_cursor }
POST/v1/conversations/{id}/tasks

タスクの承認を依頼

安定したタスクID・タイトル・本文・フォームを送信します。ユーザーの承認後にのみ実行イベントが作成されます。

リクエスト形式
{ id: ID, title: string, body?: string, category_id?: ID, fields?: Field[], inputs?: object, expires_at?: integer, result_requires_review?: boolean }
GET/v1/conversations/{id}/tasks/{task_id}

タスクの状態を取得

現在の状態・試行・入力・結果を確認します。

リクエスト形式
GET /v1/conversations/ROOM_ID/tasks/TASK_ID
→ { task }
GET/v1/conversations/{id}/tasks/{task_id}/versions

依頼のバージョンを読む

同じ依頼の以前のバージョンを確認します。

リクエスト形式
GET /v1/conversations/ROOM_ID/tasks/TASK_ID/versions
→ { versions: [{revision, title, body, fields, inputs, created_at, change_request}] }
POST/v1/conversations/{id}/tasks/{task_id}/revise

依頼の修正版を送る

所有者が承認できるよう修正した依頼を送ります。

リクエスト形式
{ request_id: ID, expected_revision: integer, change_request_id?: ID, body: string, title?: string, fields?: Field[], inputs?: object }
Only pending or changes_requested tasks can be revised. Approval is required for every new version.
POST/v1/conversations/{id}/tasks/{task_id}/claim

タスクの実行権を取得

実行トークンを保存してから試行の実行権を取得します。取得成功後にのみ外部処理を始めてください。

リクエスト形式
{ request_id: ID, attempt: integer, execution_token: string }
POST/v1/conversations/{id}/tasks/{task_id}/heartbeat

実行権を維持

現在の実行権の10分間の期限を更新します。失効した場合、タスクは要確認になります。

リクエスト形式
{ request_id: ID, attempt: integer, execution_token: string }
POST/v1/conversations/{id}/tasks/{task_id}/complete

タスクの結果を報告

結果をローカルに保存してからsucceeded・failed・needs_reviewを報告します。対応するイベントも処理済みになります。

リクエスト形式
{ request_id: ID, attempt: integer, execution_token: string, status: "succeeded" | "failed" | "needs_review", result: string, result_links?: [{label: string, url: HTTPS_URL}] }
GET/v1/conversations/{id}/actions

会話のアクション一覧

会話のフォームと現在のリビジョンを読みます。

リクエスト形式
GET /v1/conversations/ROOM_ID/actions
→ { actions }
PUT/v1/conversations/{id}/actions/{action_id}

会話のアクションを公開

フォームを作成・更新します。更新にはexpected_revisionが必要です。送信はユーザーが明示的に行います。

リクエスト形式
{ title: string, description?: string, fields: Field[], category_id?: ID, active?: boolean, expected_revision?: ID }

メディアAPI

https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouMedia
POST/v1/uploads/{id}

準備したファイルを送信

MCPのアップロード準備で取得したURLとファイル専用の認証ヘッダーで原本バイトを送信します。アカウントキーやMCP OAuthトークンで代用しないでください。

リクエスト形式
POST upload.url
Headers: upload.headers
Body: original file bytes
POST/v1/media/{id}?conversation_id={room}

写真・動画をアップロード

ファイルの原本バイトとURIエンコードしたX-Pushyou-Filenameヘッダーを送ります。同じIDとファイルで再試行してください。

リクエスト形式
Content-Type: application/octet-stream
X-Pushyou-Filename: URI_ENCODED_FILENAME
Body: original file bytes
GET/v1/media/{id}

ファイルを取得

認証ヘッダーで写真や動画を取得します。動画は単一のRangeリクエストに対応します。

リクエスト形式
Range: bytes=0-65535 (optional)
→ original file bytes
HEAD/v1/media/{id}

ファイル情報

本文をダウンロードせずにMIME形式・サイズ・Range応答ヘッダーを確認します。

リクエスト形式
HEAD /v1/media/MEDIA_ID
→ Content-Type, Content-Length, Accept-Ranges
DELETE/v1/media/{id}

未使用のアップロードを削除

まだメッセージに添付していないファイルを削除します。削除済みIDは再利用できません。

リクエスト形式
DELETE /v1/media/UNATTACHED_MEDIA_ID

07トラブルシューティング

RESTエラーは2xx以外のステータスと{"error": "…"}を返します。MCPのツールエラーはクライアントに表示されます。構造化されたエラーと接続権限を確認してください。

400ID、必須フィールド、型、カーソル、リクエストサイズを確認してください。
401再認証するか、キーの期限切れ、再発行、失効を確認してください。
403操作権限、許可された会話、会話の一時停止状態を確認してください。
404リソースIDとベースURLを確認してください。/mcpはWebページではなくプロトコルのエンドポイントです。
409異なる内容で再利用したID、古いリビジョン、タスクの実行権、添付済みのファイルなど、競合の原因を確認します。外部処理を無条件に繰り返さないでください。
410会話を削除中、またはリソースが利用できません。現在の状態を確認してください。
413JSON本文やファイルを小さくし、アップロード上限を確認してください。
415対応している画像・動画形式と正しいファイルを使ってください。
416要求したバイト範囲がファイル内か確認してください。
429リクエスト制限では間隔を空けます。メディア容量不足では未使用ファイルを整理して再試行します。新規メッセージは会話ごとに毎分60件までです。
500一時的なエラーは同じIDで間隔を空けて再試行します。外部処理が実行済みの可能性があれば、再実行前に結果を確認してください。

自分の会話に接続しますか?

接続設定で会話と権限を選び、最初のメッセージと返信を確認できます。

自分の接続を設定