Chat service interfaces provide complete chat functionality integration capabilities, including message sending and receiving, session management, voice conversion and other core functions. All interfaces require a valid API key for authentication. Use the DifyChat interface instance.
ChatMessageSendResponse send(ChatMessageSendRequest sendRequest);
ChatMessageSendRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| conversationId | String | No | Chat session number | 
| content | String | Yes | Message content | 
| files | List<ChatMessageFile> | No | file | 
| inputs | Map<String, Object> | No | Customized parameters | 
ChatMessageFile Structure:
| Parameter name | Type | Description | 
|---|
| id | String | File ID | 
| type | String | File type, default is "image" | 
| url | String | Preview image URL | 
| transferMethod | String | Transfer method, default is "remote_url" | 
| belongsTo | String | File owner, user or assistant | 
| uploadFileId | String | Upload file ID | 
ChatMessageSendResponse
| Parameter name | Type | Description | 
|---|
| conversationId | String | Chat session number | 
| messageId | String | Message id | 
| createdAt | Long | Creating timestamps | 
| taskId | String | Task id | 
| id | String | id | 
| answer | String | answer | 
Flux<ChatMessageSendCompletionResponse> sendChatMessageStream(ChatMessageSendRequest sendRequest);
Same as the Send Message interface
Returns a message stream with the following structure:
ChatMessageSendCompletionResponse
| Parameter name | Type | Description | 
|---|
| workflowRunId | String | Workflow run ID | 
| data | CompletionData | Completion data, varies by event type | 
The CompletionData structure varies depending on the event type:
| Event Type | Description | Corresponding Data Class | 
|---|
| workflow_started | Workflow started | WorkflowStartedData | 
| node_started | Node started | NodeStartedData | 
| node_finished | Node finished | NodeFinishedData | 
| workflow_finished | Workflow finished | WorkflowFinishedData | 
void stopMessagesStream(String apiKey, String taskId, String userId);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| taskId | String | Yes | taskId | 
| userId | String | Yes | userId | 
MessageFeedbackResponse messageFeedback(MessageFeedbackRequest messageFeedbackRequest);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| messageId | String | Yes | messageId | 
| rating | Rating | Yes | rating | 
| content | String | Yes | Message Feedback Specific Information | 
MessageFeedbackResponse
| Parameter name | Type | Description | 
|---|
| result | String | Fixed return success | 
DifyPageResult<MessagesResponseVO> messages(MessagesRequest request);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| conversationId | String | Yes | Chat session number | 
| firstId | String | No | First record id | 
| limit | Integer | No | Number of records per page, default 20条 | 
| Parameter name | Type | Description | 
|---|
| id | String | Message ID | 
| conversationId | String | Conversation ID | 
| inputs | Map<String, Object> | User input parameters | 
| query | String | User input/question content | 
| messageFiles | List<MessageFile> | Message files | 
| answer | String | Answer message content | 
| createdAt | Long | Creation timestamp | 
| feedback | Feedback | Feedback information | 
MessageFile Structure:
| Parameter name | Type | Description | 
|---|
| id | String | File ID | 
| filename | String | File name | 
| type | String | File type, e.g., "image" | 
| url | String | Preview image URL | 
| mimeType | String | File MIME type | 
| size | Long | File size in bytes | 
| transferMethod | String | Transfer method | 
| belongsTo | String | File owner, "user" or "assistant" | 
| uploadFileId | String | Upload file ID | 
| agentThoughts | List<MessageFileAgentThought> | Agent thoughts (not empty only in Agent mode) | 
MessageFileAgentThought Structure:
| Parameter name | Type | Description | 
|---|
| id | String | agent_thought ID, each Agent iteration has a unique id | 
| messageId | String | Message unique ID | 
| position | Integer | agent_thought position in the message, e.g., position 1 for the first iteration | 
| thought | String | Agent's thought content | 
| observation | String | Tool call result | 
| tool | String | List of tools used, separated by ; | 
| toolInput | String | Tool input, JSON formatted string (object). E.g.: {"dalle3": {"prompt": "a cute cat"}} | 
| createdAt | Long | Creation timestamp, e.g.: 1705395332 | 
| messageFiles | List<String> | File IDs associated with the current agent_thought | 
| conversationId | String | Conversation ID | 
Feedback Structure:
| Parameter name | Type | Description | 
|---|
| rating | String | like/dislike rating | 
List<String> messagesSuggested(String messageId, String apiKey, String userId);
| Parameter name | Type | Required | Description | 
|---|
| messageId | String | Yes | messageId | 
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
Return to the list of suggested response texts
DifyPageResult<AppFeedbackResponse> feedbacks(AppFeedbackPageRequest request);
AppFeedbackPageRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| page | Integer | No | Page number, default 1 | 
| limit | Integer | No | Records per page, default 20, range 1-100 | 
AppFeedbackResponse
| Parameter name | Type | Description | 
|---|
| id | String | Feedback id | 
| appId | String | Application id | 
| conversationId | String | Conversation id | 
| messageId | String | Message id | 
| rating | String | Rating (like/dislike) | 
| content | String | Feedback content | 
| fromSource | String | Source | 
| fromEndUserId | String | End user id | 
| fromAccountId | String | Account id | 
| createdAt | LocalDateTime | Creation timestamp | 
| updatedAt | LocalDateTime | Update timestamp | 
DifyPageResult<ConversationVariableResponse> conversationVariables(ConversationVariableRequest request);
ConversationVariableRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| conversationId | String | Yes | Conversation id | 
| variableName | String | No | Variable name, return all if not empty | 
ConversationVariableResponse
| Parameter name | Type | Description | 
|---|
| id | String | Variable id | 
| name | String | Variable name | 
| valueType | String | Value type (string/json) | 
| value | String | Variable value | 
| description | String | Description | 
| createdAt | Long | Creation timestamp (timestamp) | 
| updatedAt | Long | Update timestamp (timestamp) | 
ConversationVariableResponse updateConversationVariable(UpdateConversationVariableRequest request);
UpdateConversationVariableRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| conversationId | String | Yes | Conversation id | 
| variableId | String | Yes | Variable id | 
| value | String | Yes | New variable value | 
ConversationVariableResponse
| Parameter name | Type | Description | 
|---|
| id | String | Variable id | 
| name | String | Variable name | 
| valueType | String | Value type (string/json) | 
| value | String | Variable value | 
| description | String | Description | 
| createdAt | Long | Creation timestamp (timestamp) | 
| updatedAt | Long | Update timestamp (timestamp) | 
DifyPageResult<MessageConversationsResponse> conversations(MessageConversationsRequest request);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| lastId | String | No | Last record id | 
| limit | Integer | No | Number of records per page, default 20 | 
| sortBy | String | No | Sort field, default -updated_at | 
MessageConversationsResponse
| Parameter name | Type | Description | 
|---|
| id | String | Chat session number | 
| name | String | Session name | 
| inputs | Map<String,Object> | Input parameter | 
| status | String | Session state | 
| introduction | String | Opening remarks | 
| createdAt | Long | Creating timestamps | 
| updatedAt | Long | Updating timestamps | 
void deleteConversation(String conversationId, String apiKey, String userId);
| Parameter name | Type | Required | Description | 
|---|
| conversationId | String | Yes | Chat session number | 
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
MessageConversationsResponse renameConversation(RenameConversationRequest renameConversationRequest);
| Parameter name | Type | Required | Description | 
|---|
| conversationId | String | Yes | Chat session number | 
| name | String | Yes | Session name | 
| autoGenerate | String | No | Auto-generated title, default false | 
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
MessageConversationsResponse
| Parameter name | Type | Description | 
|---|
| id | String | Chat session number | 
| name | String | Session name | 
| inputs | Map<String,Object> | Input parameter | 
| status | String | Session state | 
| introduction | String | Opening remarks | 
| createdAt | Long | Creating timestamps | 
| updatedAt | Long | Updating timestamps | 
ResponseEntity<byte[]> textToAudio(TextToAudioRequest request);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| text | String | Yes | Convert Text | 
| messageId | String | No | messageId | 
Returns an audio file stream
import java.io.IOException;
private void textToAudio(TextToAudioRequest request, HttpServletResponse response) {
    try {
        ResponseEntity<byte[]> responseEntity = difyChat.textToAudio(request);
        String type = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
        response.setContentType(type != null ? type : "audio/mpeg");
        String contentDisposition = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION);
        if (contentDisposition != null) {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
        } else {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=audio.mp3");
        }
        if (responseEntity.getBody() != null) {
            response.getOutputStream().write(responseEntity.getBody());
            response.getOutputStream().flush();
        }
    } catch (Exception e) {
        log.error("textToAudio error: {}", e.getMessage());
        throw new RuntimeException("textToAudio error");
    }
}
DifyTextVO audioToText(AudioToTextRequest request);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| file | MultipartFile | Yes | Audio file | 
| Parameter name | Type | Description | 
|---|
| text | String | Convert Text | 
AppParametersResponseVO parameters(String apiKey);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
AppParametersResponseVO
| Parameter name | Type | Description | 
|---|
| openingStatement | String | Opening statement | 
| suggestedQuestions | List<String> | Opening recommended questions | 
| suggestedQuestionsAfterAnswer | Enabled | Enable recommended questions after answer | 
| speechToText | Enabled | Speech-to-text feature config | 
| textToSpeech | TextToSpeech | Text-to-speech feature config | 
| retrieverResource | Enabled | Reference and attribution config | 
| annotationReply | Enabled | Annotation reply config | 
| moreLikeThis | Enabled | More like this feature config | 
| userInputForm | List<UserInputForm> | User input form config | 
| sensitiveWordAvoidance | Enabled | Sensitive word avoidance config | 
| fileUpload | FileUpload | File upload config | 
| systemParameters | FileUploadConfig | System parameters config | 
Enabled Object Structure:
| Parameter name | Type | Description | 
|---|
| enabled | Boolean | Whether enabled | 
TextToSpeech Object Structure:
| Parameter name | Type | Description | 
|---|
| enabled | Boolean | Whether enabled | 
| voice | String | Voice type | 
FileUpload Object Structure:
| Parameter name | Type | Description | 
|---|
| enabled | Boolean | Whether file upload is enabled | 
| image | FileUploadImage | Image upload configuration | 
| allowedFileTypes | List<String>  | Allowed file types list | 
| allowedFileExtensions | List<String> | Allowed file extensions list | 
| allowedFileUploadMethods | List<String> | Allowed upload methods list | 
| numberLimits | Integer | File count limit | 
| fileUploadConfig | FileUploadConfig | Detailed upload configuration | 
FileUploadImage Object Structure:
| Parameter name | Type | Description | 
|---|
| enabled | Boolean | Whether image upload is enabled | 
| numberLimits | Integer | Image count limit, default 3 | 
| transferMethods | List<String> | Transfer methods: remote_url, local_file | 
FileUploadConfig Object Structure:
| Parameter name | Type | Description | 
|---|
| fileSizeLimit | Integer | File size limit (MB) | 
| batchCountLimit | Integer | Batch upload count limit | 
| imageFileSizeLimit | Integer | Image file size limit (MB) | 
| videoFileSizeLimit | Integer | Video file size limit (MB) | 
| audioFileSizeLimit | Integer | Audio file size limit (MB) | 
| workflowFileUploadLimit | Integer | Workflow file upload limit | 
UserInputForm Object Structure:
| Parameter name | Type | Description | 
|---|
| textInput | TextInput | Text input control config | 
| paragraph | Paragraph | Paragraph text input config | 
| select | Select | Dropdown control config | 
TextInput Object Structure:
| Parameter name | Type | Description | 
|---|
| label | String | Control display label | 
| variable | String | Control ID | 
| required | Boolean | Whether required | 
| maxLength | Integer | Maximum length limit | 
| defaultValue | String | Default value | 
Paragraph Object Structure: Inherits from TextInput, has the same field structure
Select Object Structure:
| Parameter name | Type | Description | 
|---|
| label | String | Control display label | 
| variable | String | Control ID | 
| required | Boolean | Whether required | 
| maxLength | Integer | Maximum length limit | 
| defaultValue | String | Default value | 
| type | String | Dropdown type | 
| options | List<String> | Options list | 
FileUploadResponse fileUpload(FileUploadRequest request);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| file | MultipartFile | Yes | File to upload | 
FileUploadResponse
| Parameter name | Type | Description | 
|---|
| id | String | File id | 
| name | String | File name | 
| size | Integer | File size (bytes) | 
| extension | String | File extension | 
| mimeType | String | File MIME type | 
| createdBy | String | Creator | 
| createdAt | Long | Creation timestamp | 
AppInfoResponse info(String apiKey);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
AppInfoResponse
| Parameter name | Type | Description | 
|---|
| name | String | Application name | 
| description | String | Application description | 
| tags | List<String> | Application tags list | 
AppMetaResponse meta(String apiKey);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
AppMetaResponse
| Parameter name | Type | Description | 
|---|
| toolIcons | Map<String, Object> | Tool icons mapping | 
AppSiteResponse site(String apikey);
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
AppSiteResponse
| Parameter name | Type | Description | 
|---|
| title | String | WebApp name | 
| chatColorTheme | String | Chat color theme, in hex format | 
| chatColorThemeInverted | Boolean | Whether the chat color theme is inverted | 
| iconType | IconTypeEnum | Icon type, emoji - emoji, image - picture | 
| icon | String | Icon. If it's emoji type, it's an emoji symbol; if it's image type, it's an image URL | 
| iconBackground | String | Background color in hex format | 
| iconUrl | String | Icon URL | 
| description | String | Description | 
| copyright | String | Copyright information | 
| privacyPolicy | String | Privacy policy link | 
| customDisclaimer | String | Custom disclaimer | 
| defaultLanguage | String | Default language | 
| showWorkflowSteps | Boolean | Whether to show workflow details | 
| useIconAsAnswerIcon | Boolean | Whether to replace 🤖 in chat with the WebApp icon | 
ResponseEntity<byte[]> filePreview(FilePreviewRequest request);
FilePreviewRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | userId | 
| fileId | String | Yes | Unique identifier of the file to preview, obtained from file upload API response | 
| asAttachment | Boolean | No | Whether to force the file to be downloaded as an attachment. Default is false (preview in browser) | 
Returns file content with appropriate headers for browser display or download.
- Content-Type: Set according to file MIME type
 - Content-Length: File size in bytes (if available)
 - Content-Disposition: Set to "attachment" if asAttachment=true
 - Cache-Control: Cache headers for performance
 - Accept-Ranges: Set to "bytes" for audio/video files
 
FilePreviewRequest request = new FilePreviewRequest("file-id-123")
                .setApiKey("your-api-key")
                .setUserId("user-123");
ResponseEntity<byte[]> response = difyChat.filePreview(request);
byte[] fileContent = response.getBody();
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
private void previewFile(String fileId, HttpServletResponse response) {
    try {
        FilePreviewRequest request = new FilePreviewRequest(fileId)
                .setApiKey("your-api-key")
                .setUserId("user-123")
                .setAsAttachment(false); 
        ResponseEntity<byte[]> responseEntity = difyChat.filePreview(request);
        
        String contentType = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
        response.setContentType(contentType != null ? contentType : "application/octet-stream");
        String contentLength = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH);
        if (contentLength != null) {
            response.setContentLength(Integer.parseInt(contentLength));
        }
        
        String cacheControl = responseEntity.getHeaders().getFirst(HttpHeaders.CACHE_CONTROL);
        if (cacheControl != null) {
            response.setHeader(HttpHeaders.CACHE_CONTROL, cacheControl);
        }
        
        if (responseEntity.getBody() != null) {
            response.getOutputStream().write(responseEntity.getBody());
            response.getOutputStream().flush();
        }
    } catch (Exception e) {
        log.error("File preview error: {}", e.getMessage());
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
private void downloadFile(String fileId, String filename, HttpServletResponse response) {
    try {
        FilePreviewRequest request = new FilePreviewRequest(fileId, true, "your-api-key", "user-123");
        ResponseEntity<byte[]> responseEntity = difyChat.filePreview(request);
        
        String contentType = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
        response.setContentType(contentType != null ? contentType : "application/octet-stream");
        String contentDisposition = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION);
        if (contentDisposition != null) {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
        } else {
            
            String safeFilename = filename != null ? filename : "download";
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename=\"" + safeFilename + "\"");
        }
        
        if (responseEntity.getBody() != null) {
            response.getOutputStream().write(responseEntity.getBody());
            response.getOutputStream().flush();
        }
    } catch (Exception e) {
        log.error("File download error: {}", e.getMessage());
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}
required Dify version 1.2.0 or higher
DifyPageResult<AppAnnotationResponse> pageAppAnnotation(AppAnnotationPageRequest request);
AppAnnotationPageRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| page | Integer | No | Page number, default 1 | 
| limit | Integer | No | Records per page, default 20, range 1-100 | 
AppAnnotationResponse
| Parameter name | Type | Description | 
|---|
| id | String | Annotation id | 
| question | String | Question content | 
| answer | String | Answer content | 
| hitCount | Integer | Hit count | 
| createdAt | Long | Creation timestamp | 
AppAnnotationResponse createAppAnnotation(AppAnnotationCreateRequest request);
AppAnnotationCreateRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| question | String | Yes | Question content | 
| answer | String | Yes | Answer content | 
AppAnnotationResponse
| Parameter name | Type | Description | 
|---|
| id | String | Annotation id | 
| question | String | Question content | 
| answer | String | Answer content | 
| hitCount | Integer | Hit count | 
| createdAt | Long | Creation timestamp | 
required Dify version 1.3.1 or higher
AppAnnotationResponse updateAppAnnotation(AppAnnotationUpdateRequest request);
AppAnnotationUpdateRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | apiKey | 
| userId | String | Yes | User id | 
| annotationId | String | Yes | Annotation id | 
| question | String | Yes | Question content | 
| answer | String | Yes | Answer content | 
AppAnnotationResponse
| Parameter name | Type | Description | 
|---|
| id | String | Annotation id | 
| question | String | Question content | 
| answer | String | Answer content | 
| hitCount | Integer | Hit count | 
| createdAt | Long | Creation timestamp | 
void deleteAppAnnotation(String annotationId, String apiKey);
| Parameter name | Type | Required | Description | 
|---|
| annotationId | String | Yes | Annotation id | 
| apiKey | String | Yes | apiKey | 
not have
AppAnnotationReplyResponse annotationReply(AppAnnotationReplyRequest request);
AppAnnotationReplyRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | API key | 
| userId | String | Yes | User ID | 
| action | AnnotationReplyActionEnum | Yes | Reply action type | 
| embeddingProviderName | String | No | Embedding model provider | 
| embeddingModelName | String | No | Embedding model name | 
| scoreThreshold | Float | No | Score threshold | 
AnnotationReplyActionEnum values:
- enable - Enable annotation reply
 - disable - Disable annotation reply
 
AppAnnotationReplyResponse
| Parameter name | Type | Description | 
|---|
| jobId | String | Job ID | 
| jobStatus | String | Job status | 
| errorMsg | String | Error message | 
AppAnnotationReplyResponse queryAnnotationReply(AppAnnotationReplyQueryRequest request);
AppAnnotationReplyQueryRequest
| Parameter name | Type | Required | Description | 
|---|
| apiKey | String | Yes | API key | 
| userId | String | Yes | User ID | 
| action | AnnotationReplyActionEnum | Yes | Reply action type | 
| jobId | String | Yes | Job ID to query | 
AppAnnotationReplyResponse
| Parameter name | Type | Description | 
|---|
| jobId | String | Job ID | 
| jobStatus | String | Job status | 
| errorMsg | String | Error message |