Dify Chat API Integration Guide

A practical guide to integrating with Dify's Chat API, featuring working Node.js and curl examples for building chatbots and conversational AI applications.

This guide provides verified, working code examples for integrating with Dify's Chat App API. You'll learn how to send messages, handle streaming responses, and manage conversations.

Prerequisites

Before starting, you'll need:

  • A Dify API Key (obtain from your Dify application settings)
  • Base URL: https://api.dify.ai/v1 (or your self-hosted instance URL)

Authentication

All API requests require authentication via the Authorization header:

Authorization: Bearer {YOUR_API_KEY}

[!IMPORTANT] Store your API key server-side only. Never expose it in client-side code or public repositories.


Send Chat Message

The /chat-messages endpoint is the core API for conversational interactions.

Blocking Mode

Returns the complete response after processing. Best for simple integrations.

curl Example:

curl -X POST 'https://api.dify.ai/v1/chat-messages' \
  --header 'Authorization: Bearer {YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "inputs": {},
    "query": "What is Dify?",
    "response_mode": "blocking",
    "conversation_id": "",
    "user": "user-123"
  }'

Node.js Example:

// sendMessage.js - 发送聊天消息(阻塞模式)
const DIFY_API_KEY = process.env.DIFY_API_KEY;
const DIFY_BASE_URL = 'https://api.dify.ai/v1';

async function sendMessage(query, conversationId = '', userId = 'user-123') {
  const response = await fetch(`${DIFY_BASE_URL}/chat-messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      inputs: {},
      query,
      response_mode: 'blocking',
      conversation_id: conversationId,
      user: userId,
    }),
  });

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

  return await response.json();
}

// 使用示例
const result = await sendMessage('What is Dify?');
console.log('Answer:', result.answer);
console.log('Conversation ID:', result.conversation_id);

Response Example:

{
  "event": "message",
  "message_id": "9da23599-e713-473b-982c-4328d4f5c78a",
  "conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2",
  "answer": "Dify is an open-source LLM app development platform...",
  "created_at": 1705407629,
  "metadata": {
    "usage": {
      "total_tokens": 219,
      "total_price": "0.0001395"
    }
  }
}

Returns response chunks via Server-Sent Events (SSE). Provides real-time typewriter effect.

curl Example:

curl -N -X POST 'https://api.dify.ai/v1/chat-messages' \
  --header 'Authorization: Bearer {YOUR_API_KEY}' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "inputs": {},
    "query": "What is Dify?",
    "response_mode": "streaming",
    "conversation_id": "",
    "user": "user-123"
  }'

Node.js Example:

// streamMessage.js - 流式响应处理
const DIFY_API_KEY = process.env.DIFY_API_KEY;
const DIFY_BASE_URL = 'https://api.dify.ai/v1';

async function streamMessage(query, conversationId = '', userId = 'user-123') {
  const response = await fetch(`${DIFY_BASE_URL}/chat-messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      inputs: {},
      query,
      response_mode: 'streaming',
      conversation_id: conversationId,
      user: userId,
    }),
  });

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

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let fullAnswer = '';
  let convId = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value);
    const lines = chunk.split('\n').filter(line => line.startsWith('data:'));

    for (const line of lines) {
      try {
        const data = JSON.parse(line.slice(5));
        
        if (data.event === 'message') {
          // 实时输出每个字符块
          process.stdout.write(data.answer);
          fullAnswer += data.answer;
          convId = data.conversation_id;
        } else if (data.event === 'message_end') {
          console.log('\n--- Stream ended ---');
          console.log('Usage:', data.metadata?.usage);
        } else if (data.event === 'error') {
          throw new Error(data.message);
        }
      } catch (e) {
        // 忽略解析错误(可能是 ping 事件)
      }
    }
  }

  return { answer: fullAnswer, conversationId: convId };
}

// 使用示例
const result = await streamMessage('Explain AI in simple terms');
console.log('Full answer:', result.answer);

Get Conversations

Retrieve the list of conversations for a user.

curl Example:

curl -X GET 'https://api.dify.ai/v1/conversations?user=user-123&limit=20' \
  --header 'Authorization: Bearer {YOUR_API_KEY}'

Node.js Example:

// getConversations.js - 获取会话列表
async function getConversations(userId = 'user-123', limit = 20) {
  const params = new URLSearchParams({ user: userId, limit: limit.toString() });
  
  const response = await fetch(`${DIFY_BASE_URL}/conversations?${params}`, {
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
    },
  });

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

  return await response.json();
}

// 使用示例
const conversations = await getConversations();
console.log('Conversations:', conversations.data);

Response Example:

{
  "limit": 20,
  "has_more": false,
  "data": [
    {
      "id": "10799fb8-64f7-4296-bbf7-b42bfbe0ae54",
      "name": "New chat",
      "status": "normal",
      "created_at": 1679667915,
      "updated_at": 1679667915
    }
  ]
}

Get Message History

Retrieve chat history for a specific conversation.

curl Example:

curl -X GET 'https://api.dify.ai/v1/messages?user=user-123&conversation_id={CONVERSATION_ID}&limit=20' \
  --header 'Authorization: Bearer {YOUR_API_KEY}'

Node.js Example:

// getMessages.js - 获取消息历史
async function getMessages(conversationId, userId = 'user-123', limit = 20) {
  const params = new URLSearchParams({
    user: userId,
    conversation_id: conversationId,
    limit: limit.toString(),
  });

  const response = await fetch(`${DIFY_BASE_URL}/messages?${params}`, {
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
    },
  });

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

  return await response.json();
}

// 使用示例
const messages = await getMessages('your-conversation-id');
for (const msg of messages.data) {
  console.log(`Q: ${msg.query}`);
  console.log(`A: ${msg.answer}\n`);
}

Continue a Conversation

To maintain context across messages, pass the conversation_id from the previous response:

// 继续对话示例
let conversationId = '';

// 第一条消息
const first = await sendMessage('Tell me about machine learning');
conversationId = first.conversation_id;

// 后续消息会记住上下文
const followUp = await sendMessage('How does it differ from deep learning?', conversationId);
console.log(followUp.answer); // AI会记得之前讨论的是机器学习

File Upload

For applications requiring file input (images, documents), Dify provides a file upload API:

  1. Upload the file using POST /files/upload with multipart/form-data
  2. Reference the file in your chat message using the returned upload_file_id

[!TIP] File upload is primarily used for vision-enabled models that can analyze images. Supported formats include PNG, JPG, JPEG, WEBP, and GIF.

For detailed file upload implementation, refer to the official Dify API documentation.


Error Handling

Common error codes and how to handle them:

StatusCodeDescriptionSolution
400invalid_paramInvalid parametersCheck request body format
400provider_quota_exceededModel quota exceededCheck your API credits
400model_currently_not_supportModel unavailableUse a different model
404conversation_not_existsConversation not foundStart a new conversation
500internal_server_errorServer errorRetry after a delay

Node.js Error Handling Example:

// errorHandling.js - 错误处理示例
async function safeSendMessage(query, conversationId = '') {
  try {
    return await sendMessage(query, conversationId);
  } catch (error) {
    if (error.message.includes('429')) {
      console.log('Rate limited. Waiting before retry...');
      await new Promise(r => setTimeout(r, 5000));
      return await sendMessage(query, conversationId);
    }
    
    if (error.message.includes('404')) {
      console.log('Conversation not found. Starting new conversation...');
      return await sendMessage(query, '');
    }
    
    throw error;
  }
}

Complete Example

Here's a complete Node.js chat client:

// difyClient.js - 完整的 Dify Chat 客户端
class DifyClient {
  constructor(apiKey, baseUrl = 'https://api.dify.ai/v1') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async chat(query, conversationId = '', user = 'default-user', streaming = false) {
    const response = await fetch(`${this.baseUrl}/chat-messages`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        inputs: {},
        query,
        response_mode: streaming ? 'streaming' : 'blocking',
        conversation_id: conversationId,
        user,
      }),
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || `HTTP ${response.status}`);
    }

    if (streaming) {
      return this._handleStream(response);
    }

    return await response.json();
  }

  async *_handleStream(response) {
    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      const lines = decoder.decode(value).split('\n');
      for (const line of lines) {
        if (line.startsWith('data:')) {
          try {
            yield JSON.parse(line.slice(5));
          } catch (e) {}
        }
      }
    }
  }

  async getConversations(user = 'default-user', limit = 20) {
    const params = new URLSearchParams({ user, limit: String(limit) });
    const response = await fetch(`${this.baseUrl}/conversations?${params}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` },
    });
    return await response.json();
  }

  async getMessages(conversationId, user = 'default-user', limit = 20) {
    const params = new URLSearchParams({ user, conversation_id: conversationId, limit: String(limit) });
    const response = await fetch(`${this.baseUrl}/messages?${params}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` },
    });
    return await response.json();
  }
}

// 使用示例
const client = new DifyClient(process.env.DIFY_API_KEY);

// 阻塞模式
const result = await client.chat('Hello!');
console.log(result.answer);

// 流式模式
for await (const chunk of await client.chat('Tell me a story', '', 'user-1', true)) {
  if (chunk.event === 'message') {
    process.stdout.write(chunk.answer);
  }
}

Next Steps