Assistant CoreAssistant Core
Developer API

Chat API

Tạo response, streaming SSE, upload tệp, đọc hội thoại và gửi feedback.

Base URL trong ví dụ là $ASSISTANT_API_URL. Mọi endpoint cần Bearer key và đúng scope.

Tạo chat response

POST /v1/chat/responses · scope chat:write

{
  "external_user_id": "customer_42",
  "input": "Tóm tắt chính sách đổi trả.",
  "conversation_id": "a12d5e41-7ab7-4c8f-b024-c2c38b5c43f4",
  "file_ids": ["8d50c5c2-bf85-48a4-b252-8dc97410452c"],
  "model": "optional-model-code",
  "stream": false
}
FieldBắt buộcGiới hạn và ý nghĩa
external_user_idCó1–256 ký tự; identity ổn định trong phạm vi trợ lý.
inputCó1–100.000 ký tự.
conversation_idKhôngUUID của hội thoại thuộc cùng external user. Bỏ qua để tạo hội thoại mới.
file_idsKhôngTối đa 10 UUID đã upload bởi cùng external user.
modelKhôngModel override; chỉ hoạt động nếu plan của owner cho phép.
streamKhôngMặc định false; đặt true để nhận SSE.

Request không streaming trả JSON 200. Nếu retry một request đã hoàn tất với cùng idempotency key, API trả lại metadata đã lưu với 200 kèm header Idempotent-Replayed: true; token không bao giờ được phát lại. Idempotency-Key tối đa 255 ký tự.

Streaming bằng SSE

curl -N "$ASSISTANT_API_URL/v1/chat/responses" \
  --request POST \
  --header "Authorization: Bearer $ASSISTANT_API_KEY" \
  --header "Accept: text/event-stream" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: stream-customer-42-001" \
  --data "{
    \"external_user_id\": \"$EXTERNAL_USER_ID\",
    \"input\": \"Giải thích các bước cài đặt.\",
    \"stream\": true
  }"

Mỗi event có dạng:

event: response.output_text.delta
data: {"type":"response.output_text.delta","sequence":3,"response_id":"resp_...","delta":"Xin chào"}

Event response.created xuất hiện đầu tiên. sequence tăng dần; stream kết thúc bằng đúng một response.completed hoặc error. Dòng : heartbeat có thể xuất hiện mỗi khoảng 15 giây và không có sequence.

EventNội dung chính
response.createdResponse đã bắt đầu.
conversation.createdconversation_id mới.
response.output_text.deltaPhần text trong delta.
response.reasoning.deltaPhần reasoning nếu model cung cấp.
response.tool_call.startedTool call đã bắt đầu.
response.tool_call.completedTool call đã hoàn tất.
response.file.createdTệp do response tạo.
response.completedTerminal event thành công, gồm message_id.
errorTerminal event lỗi.

Parser phải ghép nhiều delta theo sequence và xử lý Unicode bị chia giữa network chunks. Không giả định mỗi TCP chunk chứa trọn một SSE event.

Ví dụ parser Node.js/TypeScript

Ví dụ này giữ buffer giữa các network chunks và dùng streaming TextDecoder để không làm hỏng Unicode:

const response = await fetch(`${process.env.ASSISTANT_API_URL}/v1/chat/responses`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ASSISTANT_API_KEY}`,
    Accept: "text/event-stream",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    external_user_id: "customer_42",
    input: "Giải thích các bước cài đặt.",
    stream: true,
  }),
})

if (!response.ok || !response.body) {
  throw new Error(`Chat request failed: ${response.status}`)
}

const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ""

for (;;) {
  const { value, done } = await reader.read()
  buffer += decoder.decode(value, { stream: !done })

  let boundary
  while ((boundary = buffer.indexOf("\n\n")) >= 0) {
    const block = buffer.slice(0, boundary)
    buffer = buffer.slice(boundary + 2)

    if (!block || block.startsWith(":")) continue
    const data = block
      .split("\n")
      .filter((line) => line.startsWith("data:"))
      .map((line) => line.slice(5).trimStart())
      .join("\n")

    if (!data) continue
    const event = JSON.parse(data)
    if (event.type === "response.output_text.delta") {
      process.stdout.write(event.delta)
    } else if (event.type === "error") {
      throw new Error(event.message ?? "Stream failed")
    }
  }

  if (done) break
}

Idempotency

Idempotency-Key là optional nhưng nên dùng cho mọi request tạo chat:

  • Dùng một key duy nhất cho mỗi thao tác logic.
  • Cùng key và cùng body khi request đang chạy trả 409 REQUEST_IN_PROGRESS.
  • Cùng key nhưng body khác trả 409 IDEMPOTENCY_CONFLICT.
  • Metadata hoàn tất được giữ 24 giờ; lease đang chạy hết hạn sau 10 phút.
  • Retry stream không phát lại token đã nhận. Kết quả replay có id và message_id; lấy nội dung bằng GET /v1/responses/{id}.

Lấy lại response

GET /v1/responses/{response_id} · scope chat:write

curl "$ASSISTANT_API_URL/v1/responses/$RESPONSE_ID?external_user_id=$EXTERNAL_USER_ID" \
  --header "Authorization: Bearer $ASSISTANT_API_KEY"

Dùng để lấy lại kết quả khi kết nối SSE bị ngắt. Response chỉ có sau khi hoàn tất; trước đó API trả 404 RESPONSE_NOT_FOUND. status là completed, failed hoặc incomplete (client ngắt kết nối trước khi hoàn tất).

Upload tệp

POST /v1/files · scope files:write · multipart/form-data

curl "$ASSISTANT_API_URL/v1/files" \
  --request POST \
  --header "Authorization: Bearer $ASSISTANT_API_KEY" \
  --form "external_user_id=$EXTERNAL_USER_ID" \
  --form "file=@./policy.pdf"
{
  "id": "8d50c5c2-bf85-48a4-b252-8dc97410452c",
  "object": "file",
  "filename": "policy.pdf",
  "bytes": 182400,
  "mime_type": "application/pdf"
}

Kích thước tối đa là 25 MiB. Hỗ trợ PDF, DOCX, XLSX, CSV, TXT và image MIME types. Sau khi upload, truyền id trong file_ids của chat request cho cùng external user.

Đọc hội thoại

GET /v1/conversations/{conversation_id} · scope conversations:read

curl "$ASSISTANT_API_URL/v1/conversations/$CONVERSATION_ID?external_user_id=$EXTERNAL_USER_ID" \
  --header "Authorization: Bearer $ASSISTANT_API_KEY"

API trả 404 CONVERSATION_NOT_FOUND nếu assistant hoặc external user không sở hữu hội thoại.

Phân trang tin nhắn

GET /v1/conversations/{conversation_id}/messages · scope conversations:read

curl "$ASSISTANT_API_URL/v1/conversations/$CONVERSATION_ID/messages?external_user_id=$EXTERNAL_USER_ID&limit=50" \
  --header "Authorization: Bearer $ASSISTANT_API_KEY"

limit từ 1–100, mặc định 50. Tin nhắn sắp xếp từ cũ đến mới. Khi has_more là true, gửi last_id ở query parameter after của request kế tiếp. Cursor thuộc hội thoại khác trả 400 INVALID_CURSOR.

{
  "object": "list",
  "data": [
    {
      "id": "b0f16c77-a275-46c8-9dc8-8fe9fd5991cc",
      "object": "message",
      "role": "assistant",
      "content": "Nội dung phản hồi...",
      "created_at": "2026-08-13T08:30:00Z"
    }
  ],
  "has_more": true,
  "first_id": "b0f16c77-a275-46c8-9dc8-8fe9fd5991cc",
  "last_id": "b0f16c77-a275-46c8-9dc8-8fe9fd5991cc"
}

Gửi feedback

POST /v1/messages/{message_id}/feedback · scope feedback:write

curl "$ASSISTANT_API_URL/v1/messages/$MESSAGE_ID/feedback" \
  --request POST \
  --header "Authorization: Bearer $ASSISTANT_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"external_user_id\":\"$EXTERNAL_USER_ID\",\"rating\":\"up\"}"

rating chỉ nhận up hoặc down. Thành công trả 204 No Content.

Xóa end user

DELETE /v1/users/{external_user_id} · scope users:delete

curl "$ASSISTANT_API_URL/v1/users/$EXTERNAL_USER_ID" \
  --request DELETE \
  --header "Authorization: Bearer $ASSISTANT_API_KEY"

Xóa vĩnh viễn hội thoại, tin nhắn, bộ nhớ, tệp đã tải lên và dữ liệu usage của external user trong trợ lý này. Dùng cho yêu cầu xóa tài khoản hoặc xóa dữ liệu cá nhân. API idempotent và trả 204 No Content, kể cả khi user chưa từng tồn tại. Dữ liệu billing của owner không bị ảnh hưởng.

On this page