T-CREATOR

Dify の API エンドポイント徹底解説:外部連携の基本

Dify の API エンドポイント徹底解説:外部連携の基本

現代の AI 技術は目覚ましい発展を遂げており、ChatGPT や Claude、Gemini といった大規模言語モデル(LLM)がビジネスの現場で活用されるようになりました。しかし、これらの AI 技術を既存のシステムや新しいアプリケーションに組み込む際、多くの開発者が直面するのが「外部連携」の課題です。

Dify は、AI アプリケーション開発プラットフォームとして、豊富な API エンドポイントを提供し、外部システムとのシームレスな連携を可能にします。本記事では、Dify API の基本から実践的な実装方法まで、初心者の方にも理解しやすい形で徹底解説いたします。

背景

従来の AI アプリ連携の課題

これまでの AI アプリケーション開発において、外部システムとの連携は非常に複雑で時間のかかる作業でした。

従来の開発では以下のような課題がありました:

  • 認証システムの複雑さ:各 AI サービスごとに異なる認証方式への対応
  • データ形式の統一困難:サービス間でのデータフォーマットの違い
  • リアルタイム処理の実装負荷:WebSocket や SSE の実装コスト
  • エラーハンドリングの複雑性:各 API の仕様に合わせた例外処理

これらの課題により、多くの開発プロジェクトで予想以上の開発期間とコストが発生していました。

Dify の API 設計思想

Dify は、これらの従来の課題を解決するため、以下の設計思想に基づいて API を構築しています。

統一性と一貫性 すべての API エンドポイントで一貫した命名規則とレスポンス形式を採用し、学習コストを最小限に抑えています。

拡張性とモジュラー設計 機能ごとに API が分離されており、必要な機能のみを選択して利用できる柔軟な設計となっています。

開発者ファーストなアプローチ 詳細なドキュメントと豊富なサンプルコードにより、迅速な開発開始を支援します。

RESTful API の基本概念

Dify の API は、RESTful 設計原則に従って構築されています。RESTful API の基本的な概念を理解することで、より効果的に Dify API を活用できます。

#HTTP メソッド用途
1GETデータの取得アプリ一覧の取得
2POSTデータの作成新しい会話の開始
3PUTデータの更新アプリ設定の変更
4DELETEデータの削除会話の削除

Dify API の全体像

API エンドポイントの種類と分類

Dify API は、機能別に以下のカテゴリに分類されています。

アプリケーション管理系 API

  • アプリの作成、編集、削除
  • アプリ設定の管理
  • バージョン管理

会話・チャット系 API

  • 会話の開始と管理
  • メッセージの送受信
  • ストリーミング応答

ファイル・ナレッジベース系 API

  • ファイルのアップロード
  • ナレッジベースの管理
  • 文書の検索

ユーザー・認証系 API

  • ユーザー管理
  • 認証トークン管理
  • アクセス権限制御

認証方式の理解

Dify API では、セキュアな認証方式を採用しています。

API キー認証 最も基本的な認証方式で、HTTP ヘッダーに API キーを含めてリクエストを送信します。

typescriptconst headers = {
  Authorization: 'Bearer YOUR_API_KEY',
  'Content-Type': 'application/json',
};

この認証方式により、不正アクセスを防ぎつつ、シンプルな実装を可能にしています。

アクセス制御の仕組み API キーには、スコープと呼ばれる権限設定が含まれており、特定の機能のみにアクセスを制限できます。

レスポンス形式の基本構造

Dify API のレスポンスは、統一された構造を持っています。

json{
  "status": "success",
  "data": {
    // 実際のデータ
  },
  "message": "操作が正常に完了しました",
  "timestamp": "2024-01-01T00:00:00Z"
}

エラー時のレスポンス構造も一貫しており、効率的なエラーハンドリングが可能です。

json{
  "status": "error",
  "error": {
    "code": "INVALID_PARAMETER",
    "message": "パラメータが正しくありません",
    "details": "email フィールドが必須です"
  },
  "timestamp": "2024-01-01T00:00:00Z"
}

基本的な API 操作

アプリケーション管理 API

アプリケーション管理 API は、Dify アプリの基本的な操作を提供します。

アプリ一覧の取得 以下のコードで、現在利用可能なアプリの一覧を取得できます。

typescriptasync function getApplications() {
  const response = await fetch(
    'https://api.dify.ai/v1/apps',
    {
      method: 'GET',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
    }
  );

  const data = await response.json();
  return data;
}

この API を使用することで、動的にアプリ選択機能を実装できます。

新しいアプリの作成 プログラムからアプリを作成する際は、以下のようなパラメータを指定します。

typescriptasync function createApplication(appData: {
  name: string;
  description: string;
  template: string;
}) {
  const response = await fetch(
    'https://api.dify.ai/v1/apps',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(appData),
    }
  );

  return await response.json();
}

この機能により、テンプレートからアプリを自動生成するシステムを構築できます。

会話管理 API

会話管理 API は、チャットボットや AI アシスタントの核となる機能です。

新しい会話の開始 会話を開始する際は、まず会話セッションを作成します。

typescriptasync function startConversation(
  appId: string,
  userId: string
) {
  const response = await fetch(
    `https://api.dify.ai/v1/apps/${appId}/conversations`,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        user_id: userId,
        inputs: {},
      }),
    }
  );

  return await response.json();
}

メッセージの送信と応答取得 作成した会話セッションに対してメッセージを送信し、AI からの応答を取得します。

typescriptasync function sendMessage(
  appId: string,
  conversationId: string,
  message: string,
  userId: string
) {
  const response = await fetch(
    `https://api.dify.ai/v1/apps/${appId}/conversations/${conversationId}/messages`,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query: message,
        user_id: userId,
        response_mode: 'blocking',
      }),
    }
  );

  return await response.json();
}

この API により、リアルタイムなチャット機能を簡単に実装できます。

ファイル管理 API

ファイル管理 API は、ドキュメントや画像などのファイルをアップロードし、ナレッジベースとして活用する機能を提供します。

ファイルのアップロード 以下のコードで、ファイルを Dify にアップロードできます。

typescriptasync function uploadFile(file: File) {
  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch(
    'https://api.dify.ai/v1/files/upload',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
      },
      body: formData,
    }
  );

  return await response.json();
}

ファイル情報の取得 アップロードしたファイルの詳細情報を取得する際は、以下の API を使用します。

typescriptasync function getFileInfo(fileId: string) {
  const response = await fetch(
    `https://api.dify.ai/v1/files/${fileId}`,
    {
      method: 'GET',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
    }
  );

  return await response.json();
}

これらの API により、ファイルベースの RAG(Retrieval-Augmented Generation)システムを構築できます。

ユーザー管理 API

ユーザー管理 API は、マルチユーザー対応のアプリケーションを構築する際に重要な機能です。

ユーザーの作成 新しいユーザーをシステムに登録する際は、以下の API を使用します。

typescriptasync function createUser(userData: {
  user_id: string;
  name: string;
  email: string;
}) {
  const response = await fetch(
    'https://api.dify.ai/v1/users',
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(userData),
    }
  );

  return await response.json();
}

ユーザー情報の取得 特定のユーザーの情報を取得する際は、以下のように API を呼び出します。

typescriptasync function getUserInfo(userId: string) {
  const response = await fetch(
    `https://api.dify.ai/v1/users/${userId}`,
    {
      method: 'GET',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
    }
  );

  return await response.json();
}

これらの機能により、ユーザーごとに個別化された AI 体験を提供できます。

実践的な外部連携実装

Node.js での基本実装

Node.js で Dify API を活用する基本的な実装方法をご紹介します。

プロジェクトの初期化 まず、新しい Node.js プロジェクトを作成し、必要なパッケージをインストールします。

bashyarn init -y
yarn add express typescript @types/node @types/express
yarn add -D nodemon ts-node

基本的な API クライアントクラス Dify API との通信を管理するクライアントクラスを作成します。

typescriptclass DifyAPIClient {
  private apiKey: string;
  private baseURL: string;

  constructor(
    apiKey: string,
    baseURL = 'https://api.dify.ai/v1'
  ) {
    this.apiKey = apiKey;
    this.baseURL = baseURL;
  }

  private async request(
    endpoint: string,
    options: RequestInit = {}
  ) {
    const url = `${this.baseURL}${endpoint}`;
    const headers = {
      Authorization: `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json',
      ...options.headers,
    };

    const response = await fetch(url, {
      ...options,
      headers,
    });

    if (!response.ok) {
      throw new Error(
        `API request failed: ${response.statusText}`
      );
    }

    return await response.json();
  }

  async getApplications() {
    return await this.request('/apps');
  }

  async createConversation(appId: string, userId: string) {
    return await this.request(
      `/apps/${appId}/conversations`,
      {
        method: 'POST',
        body: JSON.stringify({
          user_id: userId,
          inputs: {},
        }),
      }
    );
  }

  async sendMessage(
    appId: string,
    conversationId: string,
    message: string,
    userId: string
  ) {
    return await this.request(
      `/apps/${appId}/conversations/${conversationId}/messages`,
      {
        method: 'POST',
        body: JSON.stringify({
          query: message,
          user_id: userId,
          response_mode: 'blocking',
        }),
      }
    );
  }
}

このクライアントクラスにより、型安全で再利用可能な API 操作が可能になります。

React アプリとの連携

React アプリケーションで Dify API を活用する実装例をご紹介します。

カスタムフックの作成 API 操作を React コンポーネントで利用しやすくするため、カスタムフックを作成します。

typescriptimport { useState, useCallback } from 'react';

interface UseDifyAPIProps {
  apiKey: string;
  appId: string;
}

export const useDifyAPI = ({
  apiKey,
  appId,
}: UseDifyAPIProps) => {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const sendMessage = useCallback(
    async (
      message: string,
      userId: string,
      conversationId?: string
    ) => {
      setIsLoading(true);
      setError(null);

      try {
        // 会話IDがない場合は新しい会話を作成
        if (!conversationId) {
          const conversationResponse = await fetch(
            `https://api.dify.ai/v1/apps/${appId}/conversations`,
            {
              method: 'POST',
              headers: {
                Authorization: `Bearer ${apiKey}`,
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                user_id: userId,
                inputs: {},
              }),
            }
          );
          const conversationData =
            await conversationResponse.json();
          conversationId = conversationData.data.id;
        }

        // メッセージを送信
        const messageResponse = await fetch(
          `https://api.dify.ai/v1/apps/${appId}/conversations/${conversationId}/messages`,
          {
            method: 'POST',
            headers: {
              Authorization: `Bearer ${apiKey}`,
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              query: message,
              user_id: userId,
              response_mode: 'blocking',
            }),
          }
        );

        const messageData = await messageResponse.json();
        return {
          response: messageData.data.answer,
          conversationId,
        };
      } catch (err) {
        const errorMessage =
          err instanceof Error
            ? err.message
            : '不明なエラーが発生しました';
        setError(errorMessage);
        throw err;
      } finally {
        setIsLoading(false);
      }
    },
    [apiKey, appId]
  );

  return { sendMessage, isLoading, error };
};

チャットコンポーネントの実装 作成したカスタムフックを使用して、実際のチャットインターフェースを構築します。

typescriptimport React, { useState } from 'react';
import { useDifyAPI } from './hooks/useDifyAPI';

interface Message {
  id: string;
  text: string;
  isUser: boolean;
  timestamp: Date;
}

export const ChatComponent: React.FC = () => {
  const [messages, setMessages] = useState<Message[]>([]);
  const [inputText, setInputText] = useState('');
  const [conversationId, setConversationId] =
    useState<string>('');

  const { sendMessage, isLoading, error } = useDifyAPI({
    apiKey: process.env.REACT_APP_DIFY_API_KEY!,
    appId: process.env.REACT_APP_DIFY_APP_ID!,
  });

  const handleSendMessage = async () => {
    if (!inputText.trim()) return;

    // ユーザーメッセージを追加
    const userMessage: Message = {
      id: Date.now().toString(),
      text: inputText,
      isUser: true,
      timestamp: new Date(),
    };
    setMessages((prev) => [...prev, userMessage]);
    setInputText('');

    try {
      const result = await sendMessage(
        inputText,
        'user123',
        conversationId
      );

      // 会話IDを保存
      if (!conversationId) {
        setConversationId(result.conversationId);
      }

      // AIの応答を追加
      const aiMessage: Message = {
        id: (Date.now() + 1).toString(),
        text: result.response,
        isUser: false,
        timestamp: new Date(),
      };
      setMessages((prev) => [...prev, aiMessage]);
    } catch (err) {
      console.error('メッセージの送信に失敗しました:', err);
    }
  };

  return (
    <div className='chat-container'>
      <div className='messages'>
        {messages.map((message) => (
          <div
            key={message.id}
            className={`message ${
              message.isUser ? 'user' : 'ai'
            }`}
          >
            <p>{message.text}</p>
            <small>
              {message.timestamp.toLocaleTimeString()}
            </small>
          </div>
        ))}
      </div>

      {error && (
        <div className='error-message'>エラー: {error}</div>
      )}

      <div className='input-section'>
        <input
          type='text'
          value={inputText}
          onChange={(e) => setInputText(e.target.value)}
          onKeyPress={(e) =>
            e.key === 'Enter' && handleSendMessage()
          }
          disabled={isLoading}
          placeholder='メッセージを入力してください...'
        />
        <button
          onClick={handleSendMessage}
          disabled={isLoading || !inputText.trim()}
        >
          {isLoading ? '送信中...' : '送信'}
        </button>
      </div>
    </div>
  );
};

この実装により、React アプリに本格的な AI チャット機能を簡単に組み込むことができます。

Webhook の活用方法

Webhook は、Dify からの非同期通知を受け取るための仕組みです。

Webhook エンドポイントの作成 Express.js で Webhook を受信するエンドポイントを作成します。

typescriptimport express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

// Webhookの署名検証
function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Webhook受信エンドポイント
app.post('/webhook/dify', (req, res) => {
  const signature = req.headers[
    'x-dify-signature'
  ] as string;
  const payload = JSON.stringify(req.body);

  // 署名を検証
  if (
    !verifyWebhookSignature(
      payload,
      signature,
      process.env.WEBHOOK_SECRET!
    )
  ) {
    return res
      .status(401)
      .json({ error: 'Invalid signature' });
  }

  const event = req.body;

  switch (event.type) {
    case 'conversation.completed':
      handleConversationCompleted(event.data);
      break;
    case 'message.created':
      handleMessageCreated(event.data);
      break;
    case 'workflow.completed':
      handleWorkflowCompleted(event.data);
      break;
    default:
      console.log('Unknown event type:', event.type);
  }

  res.status(200).json({ status: 'received' });
});

// イベントハンドラーの実装
function handleConversationCompleted(data: any) {
  console.log('会話が完了しました:', data);
  // 必要な後処理を実装
  // 例:データベースへの保存、メール通知など
}

function handleMessageCreated(data: any) {
  console.log('新しいメッセージが作成されました:', data);
  // リアルタイム通知の送信など
}

function handleWorkflowCompleted(data: any) {
  console.log('ワークフローが完了しました:', data);
  // 結果の処理やレポート生成など
}

app.listen(3000, () => {
  console.log('Webhook server is running on port 3000');
});

Webhook の設定 Dify 側で Webhook を設定する際は、以下のパラメータを指定します。

typescriptasync function setupWebhook(
  appId: string,
  webhookUrl: string
) {
  const response = await fetch(
    `https://api.dify.ai/v1/apps/${appId}/webhooks`,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        url: webhookUrl,
        events: [
          'conversation.completed',
          'message.created',
          'workflow.completed',
        ],
        secret: process.env.WEBHOOK_SECRET,
      }),
    }
  );

  return await response.json();
}

この設定により、Dify からの各種イベントをリアルタイムで受信し、適切な処理を実行できます。

まとめ

本記事では、Dify API エンドポイントの基本から実践的な外部連携実装まで、段階的に解説いたしました。

習得できた知識

  • RESTful API の基本概念と Dify の設計思想
  • 主要 API エンドポイントの使い方と実装方法
  • Node.js と React での実践的な連携実装
  • Webhook を活用したリアルタイム処理

Dify API の強力な機能を活用することで、従来の AI 連携で課題となっていた複雑性やコストの問題を大幅に軽減できます。統一された API インターフェースにより、学習コストを最小限に抑えながら、本格的な AI アプリケーションを構築することが可能です。

また、今回ご紹介したサンプルコードは、実際のプロジェクトでそのまま活用いただけるよう、エラーハンドリングやセキュリティ対策も含めて設計しております。これらをベースに、皆様の要件に合わせてカスタマイズしていただければと思います。

次のステップとして、より高度な機能である認証システムの実装やパフォーマンス最適化、マルチテナント対応などにも挑戦していただけると、さらに実用的な AI アプリケーションを構築できるでしょう。

関連リンク