ホーム チュートリアル カテゴリ Skills サイトについて
ZH EN JA KO
上級テクニック

OpenClaw REST API開発とサードパーティ連携チュートリアル

· 36 分で読了

はじめに

OpenClaw Gateway はチャットチャネルへのサービス提供だけでなく、完全な REST API も公開しています。これらの API を通じて、AI の能力をあらゆるアプリケーションに統合できます。自作の Web フロントエンド、CRM システム、カスタマーサポートのチケットプラットフォームなど、さまざまなシステムとの連携が可能です。本記事では、API の使い方と連携の実践方法を詳しくご紹介します。

一、API 概要

1.1 基本情報

属性
ベース URL http://localhost:18789/api/v1
プロトコル HTTP/HTTPS
データ形式 JSON
認証方式 Bearer Token
レート制限 デフォルト 60 RPM

1.2 コアエンドポイント一覧

メソッド エンドポイント 機能
POST /api/v1/chat メッセージを送信して AI の返信を取得
POST /api/v1/chat/stream ストリーミングでメッセージを送信
POST /api/v1/send 指定チャネルにメッセージを送信
GET /api/v1/conversations 会話リストの取得
GET /api/v1/conversations/:id 会話の詳細を取得
DELETE /api/v1/conversations/:id 会話を削除
GET /api/v1/skills スキルリストの取得
GET /api/v1/models 利用可能なモデルリストの取得
GET /health ヘルスチェック
GET /health/detail 詳細ステータス

二、認証設定

2.1 API Token の生成

# API Token の生成
openclaw token create --name "my-app" --scope "chat,send,read"

# 出力:
# Token: oc_tok_a1b2c3d4e5f6g7h8i9j0...
# Scope: chat, send, read
# Created: 2026-04-09

# すべての Token を表示
openclaw token list

# Token の取り消し
openclaw token revoke oc_tok_a1b2c3d4e5f6g7h8i9j0

2.2 設定ファイルでの設定

// ~/.config/openclaw/openclaw.json5
{
  "api": {
    "enabled": true,
    "port": 18789,
    "auth": {
      "enabled": true,
      "tokens": [
        {
          "name": "my-web-app",
          "token": "oc_tok_a1b2c3d4e5f6g7h8i9j0",
          "scope": ["chat", "send", "read", "admin"],
          "rateLimit": 120  // RPM
        },
        {
          "name": "crm-integration",
          "token": "oc_tok_x9y8z7w6v5u4t3s2r1q0",
          "scope": ["chat", "send"],
          "rateLimit": 30
        }
      ]
    }
  }
}

2.3 認証リクエストの例

すべての API リクエストは、Header に Token を含める必要があります:

curl -H "Authorization: Bearer oc_tok_a1b2c3d4e5f6g7h8i9j0" \
  http://localhost:18789/api/v1/models

三、コア API の使い方

3.1 メッセージ送信と返信の取得

curl の例:

curl -X POST http://localhost:18789/api/v1/chat \
  -H "Authorization: Bearer $OPENCLAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Python でクイックソートアルゴリズムを書いてください",
    "conversationId": "conv_123",
    "model": "claude-sonnet-4-20250514",
    "systemPrompt": "あなたはプロフェッショナルなプログラミングアシスタントです",
    "maxTokens": 2000,
    "temperature": 0.7
  }'

レスポンス例:

{
  "id": "msg_abc123",
  "conversationId": "conv_123",
  "role": "assistant",
  "content": "以下はPythonで実装したクイックソートアルゴリズムです:\n\n```python\ndef quicksort(arr):\n    if len(arr) <= 1:\n        return arr\n    pivot = arr[len(arr) // 2]\n    left = [x for x in arr if x < pivot]\n    middle = [x for x in arr if x == pivot]\n    right = [x for x in arr if x > pivot]\n    return quicksort(left) + middle + quicksort(right)\n```",
  "model": "claude-sonnet-4-20250514",
  "usage": {
    "inputTokens": 45,
    "outputTokens": 156
  },
  "latency": 2341
}

3.2 ストリーミング出力

curl の例(SSE):

curl -X POST http://localhost:18789/api/v1/chat/stream \
  -H "Authorization: Bearer $OPENCLAW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "message": "人工知能に関する短いエッセイを書いてください",
    "model": "claude-sonnet-4-20250514"
  }'

# SSE イベントストリームを返す:
# data: {"type":"start","conversationId":"conv_456"}
# data: {"type":"delta","content":"人工"}
# data: {"type":"delta","content":"知能"}
# data: {"type":"delta","content":"(AI)"}
# ...
# data: {"type":"done","usage":{"inputTokens":20,"outputTokens":350}}

3.3 チャネルへのメッセージ送信

# Telegram ユーザーにメッセージを送信
curl -X POST http://localhost:18789/api/v1/send \
  -H "Authorization: Bearer $OPENCLAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "telegram",
    "chatId": "123456789",
    "message": "これは API 経由で送信されたメッセージです"
  }'

# Discord チャネルにメッセージを送信
curl -X POST http://localhost:18789/api/v1/send \
  -H "Authorization: Bearer $OPENCLAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "discord",
    "chatId": "CHANNEL_ID",
    "message": "システム通知:今夜 22:00 よりサーバーメンテナンスを開始します"
  }'

四、Webhook 受信

4.1 Webhook コールバックの設定

OpenClaw がメッセージを受信したり処理を完了したりすると、アプリケーションに Webhook 通知を送信できます:

{
  "api": {
    "webhooks": {
      "outgoing": [
        {
          "url": "https://your-app.com/api/openclaw-callback",
          "secret": "your-webhook-secret",
          "events": [
            "message.received",
            "message.sent",
            "conversation.created",
            "channel.connected",
            "channel.disconnected"
          ],
          "retry": {
            "maxAttempts": 3,
            "backoffMs": 5000
          }
        }
      ]
    }
  }
}

4.2 Webhook イベント形式

{
  "event": "message.received",
  "timestamp": "2026-04-09T10:30:00Z",
  "data": {
    "messageId": "msg_xyz789",
    "conversationId": "conv_123",
    "channel": "telegram",
    "chatId": "123456789",
    "from": {
      "id": "user_456",
      "name": "Alice"
    },
    "content": "ユーザーが送信したメッセージ内容",
    "timestamp": "2026-04-09T10:30:00Z"
  },
  "signature": "sha256=abcdef..."
}

4.3 Webhook 署名の検証

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    expected = 'sha256=' + hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

五、Python 連携の例

5.1 基本的なラッパー

import requests
from typing import Optional, Generator

class OpenClawClient:
    def __init__(self, base_url: str = "http://localhost:18789",
                 token: str = ""):
        self.base_url = base_url.rstrip("/")
        self.headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json"
        }

    def chat(self, message: str, conversation_id: Optional[str] = None,
             model: str = "claude-sonnet-4-20250514",
             system_prompt: Optional[str] = None) -> dict:
        """メッセージを送信して AI の返信を取得"""
        payload = {
            "message": message,
            "model": model,
        }
        if conversation_id:
            payload["conversationId"] = conversation_id
        if system_prompt:
            payload["systemPrompt"] = system_prompt

        resp = requests.post(
            f"{self.base_url}/api/v1/chat",
            json=payload,
            headers=self.headers,
            timeout=120
        )
        resp.raise_for_status()
        return resp.json()

    def chat_stream(self, message: str,
                    model: str = "claude-sonnet-4-20250514") -> Generator:
        """ストリーミングでメッセージを送信"""
        payload = {"message": message, "model": model}
        headers = {**self.headers, "Accept": "text/event-stream"}

        resp = requests.post(
            f"{self.base_url}/api/v1/chat/stream",
            json=payload,
            headers=headers,
            stream=True,
            timeout=120
        )
        resp.raise_for_status()

        for line in resp.iter_lines():
            if line:
                line = line.decode("utf-8")
                if line.startswith("data: "):
                    yield line[6:]

    def send(self, channel: str, chat_id: str, message: str) -> dict:
        """指定チャネルにメッセージを送信"""
        resp = requests.post(
            f"{self.base_url}/api/v1/send",
            json={
                "channel": channel,
                "chatId": chat_id,
                "message": message
            },
            headers=self.headers
        )
        resp.raise_for_status()
        return resp.json()

    def health(self) -> dict:
        """ヘルスチェック"""
        resp = requests.get(f"{self.base_url}/health")
        return resp.json()


# 使用例
client = OpenClawClient(token="oc_tok_a1b2c3d4e5f6g7h8i9j0")

# 通常の会話
result = client.chat("今日の天気はどうですか?")
print(result["content"])

# ストリーミング会話
for chunk in client.chat_stream("物語を一つ話してください"):
    print(chunk, end="", flush=True)

# Telegram に送信
client.send("telegram", "123456789", "Hello from API!")

六、Node.js 連携の例

6.1 基本的なラッパー

// openclaw-client.js
const axios = require('axios');

class OpenClawClient {
  constructor(baseUrl = 'http://localhost:18789', token = '') {
    this.baseUrl = baseUrl;
    this.headers = {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
  }

  async chat(message, options = {}) {
    const { conversationId, model = 'claude-sonnet-4-20250514', systemPrompt } = options;

    const payload = { message, model };
    if (conversationId) payload.conversationId = conversationId;
    if (systemPrompt) payload.systemPrompt = systemPrompt;

    const resp = await axios.post(
      `${this.baseUrl}/api/v1/chat`,
      payload,
      { headers: this.headers, timeout: 120000 }
    );
    return resp.data;
  }

  async send(channel, chatId, message) {
    const resp = await axios.post(
      `${this.baseUrl}/api/v1/send`,
      { channel, chatId, message },
      { headers: this.headers }
    );
    return resp.data;
  }

  async health() {
    const resp = await axios.get(`${this.baseUrl}/health`);
    return resp.data;
  }

  async getModels() {
    const resp = await axios.get(
      `${this.baseUrl}/api/v1/models`,
      { headers: this.headers }
    );
    return resp.data;
  }
}

module.exports = OpenClawClient;

// 使用例
async function main() {
  const client = new OpenClawClient(
    'http://localhost:18789',
    'oc_tok_a1b2c3d4e5f6g7h8i9j0'
  );

  // 通常の会話
  const result = await client.chat('JavaScript でフィボナッチ数列を実装してください', {
    systemPrompt: 'あなたはプログラミング講師です。わかりやすく説明してください'
  });
  console.log(result.content);

  // Discord に送信
  await client.send('discord', 'CHANNEL_ID', 'API からのメッセージ');

  // 利用可能なモデルを取得
  const models = await client.getModels();
  console.log('利用可能なモデル:', models);
}

main().catch(console.error);

七、サードパーティシステムとの連携

7.1 CRM システム連携

以下の例では、OpenClaw を CRM に統合して顧客フィードバックを自動分析します:

# crm_integration.py
from openclaw_client import OpenClawClient

client = OpenClawClient(token="oc_tok_xxx")

def analyze_customer_feedback(feedback_text, customer_id):
    """顧客フィードバックを分析して分類"""
    result = client.chat(
        f"以下の顧客フィードバックを分析し、JSON 形式で結果を返してください:\n\n{feedback_text}",
        options={
            "systemPrompt": """あなたは顧客フィードバック分析の専門家です。フィードバックを分類し、以下のJSONを返してください:
{
  "sentiment": "positive/neutral/negative",
  "category": "製品品質/カスタマーサービス/価格/配送/その他",
  "urgency": "high/medium/low",
  "summary": "一文の要約",
  "suggestedAction": "推奨対応方法"
}"""
        }
    )
    return result["content"]

# 使用例
analysis = analyze_customer_feedback(
    "製品の品質がひどいです。買って2日で壊れました。しかもカスタマーサポートの態度も悪いです!",
    "CUST_001"
)
print(analysis)

7.2 チケットシステム連携

# helpdesk_integration.py
def auto_reply_ticket(ticket):
    """チケットの初期回答を自動生成"""
    result = client.chat(
        f"チケットタイトル:{ticket['title']}\n"
        f"チケット内容:{ticket['description']}\n"
        f"優先度:{ticket['priority']}\n\n"
        f"プロフェッショナルな初期回答を作成してください。",
        options={
            "systemPrompt": "あなたはテクニカルサポートの専門家です。チケット内容に基づいて初期回答と対処の提案を提供してください。回答は専業的かつ丁寧にしてください。"
        }
    )

    return {
        "reply": result["content"],
        "auto_generated": True,
        "model": result.get("model"),
        "needs_review": ticket["priority"] == "high"
    }

7.3 自作 Web フロントエンド

<!-- シンプルな Web チャットフロントエンド -->
<!DOCTYPE html>
<html>
<head>
  <title>AI アシスタント</title>
  <style>
    #chat { max-width: 600px; margin: 0 auto; padding: 20px; }
    .message { margin: 10px 0; padding: 10px; border-radius: 8px; }
    .user { background: #e3f2fd; text-align: right; }
    .assistant { background: #f5f5f5; }
    #input-area { display: flex; gap: 10px; margin-top: 20px; }
    #message-input { flex: 1; padding: 10px; border: 1px solid #ccc; border-radius: 4px; }
    button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
  <div id="chat">
    <h2>AI アシスタント</h2>
    <div id="messages"></div>
    <div id="input-area">
      <input id="message-input" placeholder="メッセージを入力..." />
      <button onclick="sendMessage()">送信</button>
    </div>
  </div>

  <script>
    const API_URL = 'http://localhost:18789/api/v1/chat';
    const TOKEN = 'oc_tok_a1b2c3d4e5f6g7h8i9j0';
    let conversationId = null;

    async function sendMessage() {
      const input = document.getElementById('message-input');
      const message = input.value.trim();
      if (!message) return;

      appendMessage('user', message);
      input.value = '';

      try {
        const resp = await fetch(API_URL, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${TOKEN}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            message,
            conversationId,
            model: 'claude-sonnet-4-20250514'
          })
        });

        const data = await resp.json();
        conversationId = data.conversationId;
        appendMessage('assistant', data.content);
      } catch (error) {
        appendMessage('assistant', 'エラーが発生しました:' + error.message);
      }
    }

    function appendMessage(role, content) {
      const div = document.createElement('div');
      div.className = `message ${role}`;
      div.textContent = content;
      document.getElementById('messages').appendChild(div);
      div.scrollIntoView({ behavior: 'smooth' });
    }

    document.getElementById('message-input')
      .addEventListener('keydown', e => { if (e.key === 'Enter') sendMessage(); });
  </script>
</body>
</html>

八、API レート制限

8.1 レート制限の設定

{
  "api": {
    "rateLimit": {
      // グローバル制限
      "global": {
        "windowMs": 60000,    // 1分間のウィンドウ
        "maxRequests": 120    // 最大 120 回
      },
      // Token 別の制限
      "perToken": {
        "windowMs": 60000,
        "maxRequests": 60
      }
    }
  }
}

8.2 レート制限エラーの処理

レート制限がトリガーされると、API は 429 Too Many Requests を返します:

{
  "error": "rate_limit_exceeded",
  "message": "リクエスト頻度が高すぎます。しばらくしてから再度お試しください",
  "retryAfter": 30
}

クライアント側でリトライロジックを実装します:

import time

def chat_with_retry(client, message, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.chat(message)
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:
                retry_after = int(e.response.headers.get('Retry-After', 30))
                print(f"レート制限中、{retry_after}秒後にリトライします...")
                time.sleep(retry_after)
            else:
                raise
    raise Exception("最大リトライ回数を超過しました")

九、セキュリティのベストプラクティス

対策 説明
HTTPS の使用 本番環境では必ず Nginx リバースプロキシで HTTPS を有効化
Token 権限の最小化 必要な scope のみ付与
IP ホワイトリスト API アクセス元を制限
入力バリデーション ユーザー入力をサニタイズし、プロンプトインジェクションを防止
ログ監査 すべての API 呼び出しを記録
定期的な Token ローテーション 90日ごとに交換
{
  "api": {
    "security": {
      // IP ホワイトリスト
      "allowedIPs": ["10.0.0.0/8", "192.168.1.0/24"],
      // CORS 設定
      "cors": {
        "enabled": true,
        "origins": ["https://your-app.com"],
        "methods": ["GET", "POST", "DELETE"]
      },
      // リクエストボディサイズの制限
      "maxBodySize": "1MB"
    }
  }
}

十、デバッグとトラブルシューティング

# API リクエストログの確認
openclaw logs | grep -i "api\|request\|response"

# verbose curl でデバッグ
curl -v -X POST http://localhost:18789/api/v1/chat \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"test"}'

# API サービスの状態を確認
curl -s http://localhost:18789/health | jq .

以上の API 連携ソリューションにより、OpenClaw の AI 能力をあらゆる既存システムにシームレスに統合し、強力なインテリジェントアプリケーションを構築することができます。

OpenClawは無料のオープンソースAIアシスタント。WhatsApp、Telegram、Discordなど多数のプラットフォームに対応