タスク
概要
タスクは、ChatGPT や Claude などの AI にあなたのサーバー(ワーカー)で作業を実行させる機能です。「ERP に A-1042 を 30 個発注して」と伝えると、AI がワーカーに作業を送り、結果を受け取って会話に表示します。
- 3Min API は作業を届けて状態を記録するだけで、作業そのものはワーカーが実行します
- ワーカーは、あなた自身が運用する HTTP サーバーです
いつ使うか
- 社内システムに作業させたいとき — ERP への発注登録、在庫確認、社内 DB の検索
- 時間のかかる作業 — レポート生成、大量変換(最大 24 時間)
- 自分の PC でしか動かないスクリプト — トンネルで公開 URL を付ければ使えます(下記参照)
データを保存・収集することが目的なら、エンドポイントが適しています。
ワーカーのコードを書くのが難しければ、普段使っている AI に「3minapi のタスクワーカーを作って」と頼んでみてください。AI は
helpツールからこのページと同じ約束事を読み取り、コードを書きます。
このページへのアクセス方法
- ワーカーの登録: ダッシュボード → タスク → ワーカー タブ →
ワーカーを登録 - 実行の確認: ダッシュボード → タスク → 実行履歴 タブ
動作の仕組み
① Web でワーカーを登録 (最初に一度だけ)
② AI → task_create タスク作成、状態 working
③ 3Min API → ワーカーへ POST 署名付きリクエスト(callback_url を含む)
④ ワーカー → すぐに 2xx を返す 「受け取った」という意味だけで、結果ではない
⑤ ワーカー → callback_url 進捗メッセージ(任意) → completed または failed
⑥ AI → task_get 結果を確認
| どこで | すること |
|---|---|
| Web ダッシュボード | ワーカーの登録・編集・削除、シークレットの確認・更新、実行履歴の確認 |
| AI との会話 | ワーカー一覧の確認、タスクの送信、状態・結果の確認、キャンセル |
| ワーカーサーバー | リクエストの受信、作業の処理、結果の報告 |
AI はワーカーの URL とシークレットを見ることができません。どちらも Web でのみ扱います。
ワーカーの登録 (Web)
| 項目 | 説明 | 上限 |
|---|---|---|
| 名前 | 必須。AI が呼ぶ名前。大文字・小文字を区別せず一意で、登録後は変更不可 | 50 文字 |
| 説明 | 必須。AI はこの説明を見てワーカーを選びます | 500 文字 |
| ワーカー URL | 必須。タスクを POST で受け取るアドレス | 2,048 バイト |
| 認証ヘッダー / 認証値 | 任意。ワーカー独自の認証用。値だけ入れるとヘッダーは Authorization |
128 / 8,192 バイト |
- 説明は具体的に書いてください。 AI は URL ではなく名前と説明だけを見ます。
erp-1ではなく「社内 ERP に発注を登録し、発注番号を返します」のように、何を受け取り何を返すかを書くと AI が選べます
2つのシークレットは方向が逆
登録すると、シークレットが 2 つ自動で発行されます。ワーカーの詳細画面(ダッシュボード → タスク → ワーカー タブ → ワーカーを選択)の シークレットを表示・シークレットをコピー で確認してください。
| シークレット | 形式 | 方向 | 用途 |
|---|---|---|---|
| 署名シークレット | whsec_... |
3Min API → ワーカー | 届いたリクエストが本当に 3Min API から来たかを検証 |
| コールバックキー | tm_task_... |
ワーカー → 3Min API | 報告するときに Authorization: Bearer で送信 |
- 2 つは別の値で、入れ替えて使えません。 エンドポイントの API キー(
tm_live_・tm_test_)もコールバックキーとしては使えません
| 変更 | 動作 | ワーカーがすること |
|---|---|---|
署名シークレットを再発行 |
48 時間は新しいタスクに新旧両方の署名が付く。再発行前のタスクの再試行(最大約 5 時間)には以前の署名だけが付く | 以前のシークレットを 6 時間以上残してから、48 時間以内に切り替え |
コールバックキーを再生成 |
以前のキーは即座に無効(実行中のタスクも含む) | すぐに切り替え |
48 時間以内にもう一度再発行すると、最初のシークレットは即座に無効になります。ダッシュボードには現在のシークレットだけが表示されるため、以前のシークレットを残すには再発行する前にコピーしておいてください。
ワーカーの実装
ワーカーが守る5つのルール
- 15 秒以内に 2xx を返してください。 作業は応答した後に処理します
- 作業が失敗しても、リクエストは 2xx で受け取ってください。 失敗は報告で伝えます(5xx は再試行、それ以外の 4xx は即時失敗 — 応答コード)
task_idで重複を除いてください。 同じタスクが 2 回届くことがあります(at-least-once)- 署名検証は任意ですが推奨です。 検証しないと、ワーカー URL を知る誰でも偽のタスクを送れます(署名検証)
- 結果は
callback_urlに報告してください。completedまたはfailedを 1 回送ります。報告がなければ 24 時間後にfailedになります(ステータス報告 API)
配信リクエスト
3Min API がワーカー URL に送るリクエストです。
POST https://worker.example.com/tasks
Content-Type: application/json
webhook-id: 0199a1b2-...
webhook-timestamp: 1757650867
webhook-signature: v1,K3XkZ1n0...
X-3minapi-Task-Id: 0199a1b2-...
X-3minapi-Delivery-Attempt: 1
Authorization: Bearer xxx
| ヘッダー | 内容 |
|---|---|
webhook-id |
タスク ID(task_id と同じ値) |
webhook-timestamp |
送信時刻(Unix 秒)。試行ごとに新しくなる |
webhook-signature |
署名。再発行中はスペース区切りで 2 つ(署名検証) |
X-3minapi-Task-Id |
タスク ID(webhook-id と同じ値) |
X-3minapi-Delivery-Attempt |
何回目の配信試行か(1 から) |
| 登録した認証ヘッダー | 登録時に認証ヘッダー・値を入力した場合のみ |
本文:
{
"type": "task.created",
"timestamp": "2026-09-12T04:21:07.123Z",
"data": {
"task_id": "0199a1b2-...",
"input": { "sku": "A-1042", "qty": 30 },
"callback_url": "https://api.3minapi.com/api/v1/tasks/0199a1b2-.../result"
}
}
| フィールド | 内容 |
|---|---|
task_id |
タスク ID。重複除去に使います |
input |
AI が送った JSON オブジェクト(値は同じでもキーの順序は変わることがあります) |
callback_url |
このタスクの報告先 URL。 状態・結果はここに送ります |
ワーカーの応答コード
応答の本文は読まず、ステータスコードだけを見ます。
| 応答 | 結果 |
|---|---|
| 2xx | 受付完了。報告が届くまで working |
| 5xx(501・505 を除く)、429、15 秒タイムアウト、接続エラー | 30 秒・2 分・10 分・1 時間・4 時間後に再試行、計 6 回(約 5 時間)。429 の Retry-After は長い場合のみ反映 |
| その他の 4xx(401・404・409 など)、501、505 | 再試行せず即座に failed |
- 署名検証に失敗したら 401 を返してください。シークレットを間違えて入力していれば、最初のタスクからすぐに
failedになり、設定の問題にすぐ気づけます
署名検証 (任意)
webhook-signature ヘッダーが署名です。3Min API がワーカーの署名シークレットで計算して付け、ワーカーは同じ計算で一致するかを確認します。
署名対象 = "{webhook-id}.{webhook-timestamp}.{リクエスト本文の生データ}"
キー = 署名シークレットから whsec_ を除き、base64 デコードしたバイト列
署名 = "v1," + base64( HMAC-SHA256(キー, 署名対象) )
- 公式の Standard Webhooks ライブラリを使えば数行で済みます(サンプルコード)。言語別パッケージと自前実装の方法は Webhook 署名の検証(同じ規格)を参照してください
- リクエスト本文の生のバイト列で検証してください。JSON をパースしてから文字列に戻すと必ず失敗します
webhook-timestampが 5 分以上ずれていると、ライブラリが拒否します(リプレイ攻撃の防止)- 署名が 2 つ届いた場合は、どちらか一方が一致すれば合格です(再発行のルール)
- 検証しない場合は、少なくとも
callback_urlがhttps://api.3minapi.com/で始まるかを確認してください — コールバックキーをそのアドレスに送るためです
ステータス報告 API
配信リクエストで届いた callback_url に状態を送ります。進捗メッセージは何度でも、完了・失敗は 1 回だけです。
POST https://api.3minapi.com/api/v1/tasks/{task_id}/result
Authorization: Bearer tm_task_...
Content-Type: application/json
- URL:
callback_urlはこの形式にタスク ID が埋め込まれた状態で届きます。自分で組み立てず、そのまま使ってください - コールバックキー: ワーカー詳細画面の コールバックキー →
シークレットをコピー。ワーカーサーバーの環境変数などに保存してください
進行中 — タスクは working のままで、AI は task_get でメッセージを確認します
{ "status": "working", "status_message": "1/2 在庫を確認中" }
完了
{
"status": "completed",
"result": { "order_id": "PO-20260912-001" },
"status_message": "発注 PO-20260912-001 を登録しました"
}
失敗
{
"status": "failed",
"error": { "code": 1001, "message": "在庫不足", "data": { "available": 12 } }
}
| フィールド | ルール |
|---|---|
status |
working・completed・failed のいずれか |
status_message |
working では必須、それ以外は任意。256 文字を超えた分は切り捨て。failed で省略すると error.message が入る |
result |
completed では必須。null 以外の任意の JSON |
error |
failed では必須。code(整数)+ message(文字列)、data は任意 |
- 本文全体を 100 KB 以下にしてください。
result・errorは切り捨てられないため、超えると報告全体が 413 で拒否されます - 受け付けられた報告 1 回 = API 呼び出し 1 回。進捗メッセージは意味のある段階でだけ送ってください
ステータス報告 API の応答コード
| コード | 意味 | ワーカーの対応 |
|---|---|---|
| 202 | 受付済み。通常は数秒以内に反映 | — |
| 400 | 本文の形式エラー、不正なタスク ID、文字列内の NUL 文字 | コードを修正 |
| 401 | コールバックキーがない・誤り(エンドポイントの API キーを含む) | キーを確認 |
| 404 | このワーカーのタスクではない | callback_url を確認 |
| 409 | すでに終了したタスク(完了・失敗・キャンセル) | 報告をやめる |
| 413 | 本文が 100 KB を超過。何も記録されない | タスクがまだ working なら縮めて再送 |
| 415 | Content-Type が JSON ではない | ヘッダーを修正 |
| 503 | 一時的な障害 | 少し待って再送 |
サンプルコード (Node.js)
Node.js 18 以上と、package.json の "type": "module" が必要です。
// npm i express standardwebhooks
import express from 'express';
import { Webhook } from 'standardwebhooks';
// 署名シークレット(whsec_...)とコールバックキー(tm_task_...)は別の値です
const wh = new Webhook(process.env.TASK_SIGNING_SECRET.replace('whsec_', ''));
const CALLBACK_KEY = process.env.TASK_CALLBACK_KEY;
// 受け付けた task_id — 本番では DB や Redis に保存してください
const seen = new Set();
const app = express();
// 署名は生のバイト列で計算されます。JSON をパースすると検証に失敗します。
app.post('/tasks', express.raw({ type: 'application/json' }), (req, res) => {
let envelope;
try {
envelope = wh.verify(req.body, {
'webhook-id': req.header('webhook-id'),
'webhook-timestamp': req.header('webhook-timestamp'),
'webhook-signature': req.header('webhook-signature')
});
} catch {
return res.sendStatus(401);
}
const { task_id, input, callback_url } = envelope.data;
// ルール 3 — 受け付け済みのタスクは再処理しない
if (seen.has(task_id)) return res.sendStatus(202);
seen.add(task_id);
// ルール 1 — 先に応答し、作業はその後で
res.sendStatus(202);
run(input, callback_url);
});
async function run(input, callbackUrl) {
try {
// 進捗メッセージ — タスクは working のまま、AI は task_get で確認します
await report(callbackUrl, { status: 'working', status_message: '1/2 在庫を確認中' });
await checkStock(input); // ← 実際の作業
await report(callbackUrl, { status: 'working', status_message: '2/2 発注を登録中' });
const orderId = await createOrder(input);
// 完了 — 結果と要約メッセージ
await report(callbackUrl, {
status: 'completed',
result: { order_id: orderId },
status_message: `発注 ${orderId} を登録しました`
});
} catch (err) {
// ルール 2 — 作業や報告が失敗したら failed を報告
await report(callbackUrl, {
status: 'failed',
error: { code: 1001, message: String(err?.message ?? err) },
status_message: '発注の登録に失敗しました'
}).catch(console.error);
}
}
// callbackUrl — 配信リクエストの callback_url をそのまま使う
async function report(callbackUrl, body) {
for (let attempt = 1; attempt <= 3; attempt++) {
const res = await fetch(callbackUrl, {
method: 'POST',
headers: {
Authorization: `Bearer ${CALLBACK_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
}).catch(() => null);
// 202 受付、409 すでに終了したタスク — これ以上送る必要なし
if (res?.status === 202 || res?.status === 409) return;
// 400・401・404・413 は再送しても同じ結果
if (res && res.status !== 503) throw new Error(`report rejected: HTTP ${res.status}`);
// 503・ネットワークエラーだけ少し待って再試行
if (attempt < 3) await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
}
throw new Error('report failed: service unavailable');
}
app.listen(8080);
自分のPCでワーカーを動かす
ワーカーにはインターネットから届く公開 URL が必要です。ルーターの内側にある PC なら、トンネルでローカルのポートに公開 HTTPS アドレスを付けてください。
cloudflared tunnel --url http://localhost:8080
ngrok http 8080
- インストールと使い方: Cloudflare Quick Tunnels・ngrok はじめに
- 表示されたアドレスにパスを付けて(例:
https://xxxx.trycloudflare.com/tasks)ワーカー URL として登録します - アカウントなしの一時アドレスは起動するたびに変わります。 そのたびにワーカー URL を更新するか、各サービスの固定アドレス機能を使ってください
- PC の電源が切れている、またはトンネルが切れている場合、たいていは再試行(約 5 時間)の後に
failedになります。停止中のアドレスに 404 を返すサービスでは、すぐにfailedになります
タスクの送信 (AI)
ワーカーを登録すれば、AI との会話ですぐに使えます。ツール名を知る必要はありません。
- 「ERP に A-1042 を 30 個発注して」
- 「さっき送った発注はどうなった?」
- 「今送ったタスクをキャンセルして」
| ツール | すること |
|---|---|
worker_list |
登録済みワーカーの名前と説明(URL・シークレットは見えない) |
task_create |
ワーカーの名前と input(JSON オブジェクト、100 KB 以下)でタスクを作成 |
task_get |
タスク 1 件の状態、メッセージ、結果またはエラー |
task_list |
最近のタスク一覧(結果の本文は含まない) |
task_cancel |
実行中のタスクをキャンセル(最大 100 件) |
- 同じワーカーに同じ
inputを 2 分以内に(タイミングにより最大約 4 分)送ると、既存のタスクが返されます。完了・キャンセル済みのタスクもそのまま返され、失敗したタスクだけが新しく作られます - キャンセルはワーカーに通知されません。 残りの配信試行が止まるだけで、すでに受け取ったワーカーからの以後の報告は 409 になります
ステータスの確認
| 状態 | 意味 | 変わるか |
|---|---|---|
working |
配信中、またはワーカーが処理中 | 変わる |
completed |
ワーカーが完了を報告 | 最終 |
failed |
ワーカーの失敗報告、配信の失敗、または 24 時間経過 | 最終 |
cancelled |
キャンセル済み | 最終 |
failed の理由は status_message に残ります。
| 原因 | status_message の例 |
|---|---|
| ワーカーが失敗を報告 | ワーカーが送ったメッセージ(なければ error.message) |
| 再試行を使い切った | The task could not be delivered to the worker after 6 attempts (no response within 15s). |
| 即時失敗の応答 | The task could not be delivered to the worker after 1 attempt (HTTP 401). |
| 24 時間経過 | Worker did not respond within 24 hours. |
確認できる場所:
- AI —
task_get・task_list。ワーカーのresultは要約されずにそのまま渡されます - Web — 実行履歴 タブ。期間(7・30・60 日、Free は 7 日)と状態で絞り込み、行をクリックすると入力・結果・エラー・配信が見られます。配信が最終的に失敗した場合、配信 に試行回数・最後の応答・理由が表示されます
制限事項
| 項目 | 値 |
|---|---|
| ワーカー数 | Free 1 個 / 有料プランは無制限 |
| タスク数・同時実行 | 無制限(月間 API 呼び出し上限の範囲内) |
| 期限 | 作成から 24 時間 — 過ぎると failed(1 時間ごとの確認のため最大約 25 時間) |
| 履歴の保存 | 有料プランは最低 60 日 / Free はワーカー登録から 7 日後にワーカーと実行履歴をすべて削除 |
input のサイズ |
100 KB |
| 報告の本文 | 100 KB(status_message は 256 文字で切り捨て) |
| 配信タイムアウト・再試行 | 15 秒・計 6 回、約 5 時間 |
| 署名シークレット再発行の猶予 | 48 時間 |
| コールバックキーの再生成 | 以前のキーは即座に無効 |
| API 呼び出しのカウント | 成功したタスクツール呼び出し 1 回・受け付けられた報告 1 回がそれぞれ 1 回。配信・再試行は 0 回。上限を超えても報告は受け付けます |
| 配信の保証 | at-least-once(同じタスクが 2 回届くことがある) |
個人情報について
- ワーカーの
result・errorはマスキングされずにそのまま AI との会話に渡されます - 3Min API は自由形式の JSON から個人情報を判別しないため、結果に必要以上の個人情報を含めないでください
トラブルシューティング
- すべてのタスクがすぐ
failedになる: 実行詳細の 配信 → 最後の応答 を確認してください。401 なら、署名シークレットの欄にコールバックキーを入れたか、再発行直後に以前のシークレットを消した可能性があります - タスクが
workingのまま: ワーカーが 2xx を返すだけで報告していません。ワーカーのログでステータス報告 API の応答コードを確認してください - 報告が 401 になる:
tm_task_で始まるコールバックキーか、再生成前のキーではないかを確認してください - 報告が 409 になる: すでに終了またはキャンセルされたタスクです。これ以上送る必要はありません
- 報告が 413 になる: 本文が 100 KB を超えています。
resultを縮めて再送してください - 同じリクエストなのに新しいタスクができない: 2 分以内の同じ
inputは既存のタスクを返します。日付などをinputに入れて区別してください