🚀 Simplify your work by integrating Haufe Copilot via API
Validation

Message Validation

Validation rules applied to the messages collections in Chat Completions and Run requests.

The following rules are enforced on message stacks: Either directly provided via /chat/completions or built server-side by attaching messages to a thread.

All violations return an HTTP 422 Unprocessable Entity.

Content Rules

These rules apply to the content field of every message type.

RuleDetails
Non-emptycontent must not be blank or whitespace-only (applies to user, system, and tool messages)
Maximum lengthcontent must not exceed 30,000 characters
Valid Unicodecontent must be valid UTF-8; broken Unicode characters are rejected

Assistant message content

assistant messages follow a slightly different rule:

  • content must be non-empty when tool_calls is absent.
  • content must be empty when tool_calls is present.

Message List Rules

RuleDetails
Non-empty listThe messages array must contain at least one message
Last messageThe last message must have role user or tool
System message uniquenessAt most one system message is allowed
Assistant message orderingAn assistant message must be directly preceded by a user message

Example — valid message stack

[
  { "role": "system",    "content": "You are a helpful HR expert." },
  { "role": "user",      "content": "What is BEM?" },
  { "role": "assistant", "content": "BEM stands for ...", "sources": [] },
  { "role": "user",      "content": "Can you elaborate?" }
]

Example — invalid: assistant without preceding user message

[
  { "role": "system",    "content": "You are a helpful HR expert." },
  { "role": "assistant", "content": "BEM stands for ...", "sources": [] }
]

Attachment Rules

Attachments can be added to user messages via the attachments field.

Recommended flow: upload the file through the /files endpoints, set user_id either on the thread (POST /threads) or on the chat-completions request body (POST /chat/completions), and reference the file by its file_id only — leave AttachmentCreate.user_id and AttachmentCreate.base_url empty.

RuleDetails
Maximum attachments3 attachments per user message. More are rejected with HTTP 422 and error code user_message_too_many_attachments.
Uniqueness within a messageThe same attachment must not be listed twice on one user message. Rejected with HTTP 422 and error code user_message_not_unique_attachments.
Global uniquenessEach attachment is identified by its file_id, user_id, and base_url. The same attachment must not appear more than once across all messages in a single request. Rejected with HTTP 422 and error code attachment_not_unique.
user_id optional, do not setShould be left empty. Provide the user_id once on the thread (POST /threads) or on the chat-completions request body (POST /chat/completions). The AttachmentCreate.user_id override is intended for internal usage only.
base_url optional, do not setDefaults to the production file storage URL. The AttachmentCreate.base_url override is intended for internal usage only — e.g. when referencing a file on a non-production environment. A URL outside the allowed set is rejected with HTTP 422 and error code attachment_url_invalid.
User ID must be resolvableIf a message carries an attachment, a user_id must be available somewhere — on the thread, on the request body, or (for internal use) on the attachment itself. If none is set the request is rejected with HTTP 422 and error code attachment_requires_user_id.
File must existThe file_id must exist on the file storage service for the resolved user_id. Unknown or already deleted files are rejected with HTTP 404 and error code attachment_document_does_not_exist.
File must be accessibleIf the resolved user_id is not allowed to read the file, the request is rejected with HTTP 403 and error code attachment_access_forbidden.
File must be processedThe file must have reached PROCESSED state on the file storage service before it can be attached. Files that are not finished yet — still uploading, being scanned, or still being processed — return HTTP 409 with error code attachment_document_still_processing; retry once processing completed. Files that finished in any other state return HTTP 400 with error code attachment_document_raised_an_error.
File must be cleanA file the storage service flagged as infected is rejected with HTTP 409 and error code conflict.
File must contain textIf no text could be extracted from the file (warnings.empty on GET /files/{file_id}/status), the request is rejected with HTTP 422 and error code attachment_is_below_minimum_size. There is no minimum length beyond that.
Extracted text must fit the limitThe extracted text must not exceed 60,000 characters, measured on the whole document. Longer documents are rejected with HTTP 422 and error code attachment_exceeds_max_size. Split large documents into several files.
Non-persisted files expireFiles uploaded with persist=false (via GET /files/signed-url) are only retained for 24 hours. After that they cannot be used for answer generation. Use persist=true (the default) for files that should remain available longer.
info

These checks run when the attachment is added to a message. The file content itself is only loaded when an answer is generated, so a file that was deleted in the meantime does not fail the request — it is reported back in meta_data.attachments instead. See Uploading Files.

warning

Validating an attachment requires calls to the file storage service. If that service is unreachable, the request fails with HTTP 502 and error code attachment_document_not_reachable. Unlike the rules above this is transient and not caused by your request — retry it.

Tool Message Rules

Tool messages (role: "tool") return tool call results to the assistant.

RuleDetails
Must follow an assistant messageA tool message must be preceded by an assistant message that requested the corresponding tool call
All requested tool calls must be answeredIf an assistant message requests multiple tool calls, all corresponding tool messages must immediately follow it
Unique tool_call_idEach tool_call_id must be unique across the entire messages array

Example — valid tool message sequence

[
  { "role": "user", "content": "Search for BEM regulations." },
  { "role": "assistant", "content": "", "sources": [], "tool_calls": [
      { "id": "call_1", "type": "function", "function": { "name": "search", "arguments": "{}" } },
      { "id": "call_2", "type": "function", "function": { "name": "fetch", "arguments": "{}" } }
  ]},
  { "role": "tool", "content": "Search result...", "tool_call_id": "call_1" },
  { "role": "tool", "content": "Fetch result...", "tool_call_id": "call_2" }
]

Example — invalid: missing tool message for call_2

[
  { "role": "user", "content": "Search for BEM regulations." },
  { "role": "assistant", "content": "", "sources": [], "tool_calls": [
      { "id": "call_1", "type": "function", "function": { "name": "search", "arguments": "{}" } },
      { "id": "call_2", "type": "function", "function": { "name": "fetch", "arguments": "{}" } }
  ]},
  { "role": "tool", "content": "Search result...", "tool_call_id": "call_1" }
]

Tool Choice Rules

When using the tools and tool_choice fields on the request:

RuleDetails
tool_choice requires toolstool_choice cannot be set if tools is absent or empty
Named tool choice must be validIf tool_choice specifies a function by name, that function must be present in the tools list

Defaults:

  • If tools is provided but tool_choice is omitted, it defaults to "auto".
  • If neither is provided, tool_choice defaults to "none".

On this page