# LLM 채팅 API 레퍼런스



선택한 모델에 질문이나 대화 기록을 보내고 답변을 받는 API의 전체 명세입니다. 입력 항목, 응답 필드, SSE 형식, 오류와 요금을 모두 정리했습니다.



인증: Authorization: Bearer $APICK_API_KEY

본문 있는 REST 요청: multipart/form-data. GET 본문 및 MCP JSON-RPC 규격은 해당 명세를 따릅니다.

인증키는 서버에 보관하세요. 모든 예제는 정적 자료입니다.



## POST /rest/llm/chat 응답 필드

- `data` (object): 요청 처리 결과 묶음입니다. 조회한 값·작업 상태·오류 설명이 이 안에 들어 있으며, 실제 하위 필드 구성은 서비스마다 다릅니다. 값이 없으면 null·빈 배열·필드 생략 중 해당 서비스의 규칙을 따릅니다.

- `data.model` (string): 응답을 생성한 모델 ID입니다. 요청에서 지정한 모델과 같으며, 모델 목록 API의 id 값과 비교해 확인합니다.

- `data.message` (object): 모델이 생성한 응답 메시지 묶음입니다. 작성자 역할과 답변 본문이 들어 있습니다.

- `data.message.role` (string): 메시지 작성자 역할입니다. 응답에서는 assistant입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.message.content` (string): 모델이 생성한 답변 텍스트입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.usage` (object): 이번 응답의 토큰 사용량 묶음입니다. 입력·출력·합계 토큰 수가 들어 있으며 과금 계산의 기준이 됩니다.

- `data.usage.prompt_tokens` (integer): 입력(프롬프트)에 사용한 토큰 수입니다. 과금 계산의 입력 단가에 적용됩니다.

- `data.usage.completion_tokens` (integer): 출력(응답)에 사용한 토큰 수입니다. 과금 계산의 출력 단가에 적용됩니다.

- `data.usage.total_tokens` (integer): 입력과 출력 토큰을 합한 수입니다. 숫자로 오며, 단위·범위는 같은 응답의 다른 필드나 이 문서의 설명을 확인하세요.

- `data.compacted_messages` (array): 문맥 압축으로 요약된 이전 메시지 목록입니다. 대화가 길어져 오래된 메시지를 압축했을 때 포함됩니다.

- `data.compacted_messages[].role` (string): 압축된 이전 메시지의 작성자 역할입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.compacted_messages[].content` (string): 문맥 압축으로 요약된 이전 메시지 내용입니다. 문자열로 오며, 값이 없으면 빈 문자열이거나 필드가 생략됩니다. 같은 응답의 다른 필드와 함께 해석하세요.

- `data.ic_id` (undefined): 이번 조회에 부여된 식별자입니다. 같은 요청의 결과를 추적하거나 문의할 때 사용하며, 값이 없으면 null입니다. null 허용.

- `data.result` (integer): 조회 결과 본문입니다. 서비스가 찾은 실제 데이터가 들어 있으며, 자료가 없거나 조회에 실패하면 null이거나 필드가 생략됩니다.

- `data.msg` (string): 처리 결과를 사람이 읽을 수 있는 문장으로 설명합니다. 성공·실패 사유가 담기며, 오류 코드는 별도 필드에서 확인합니다.

- `data.success` (integer): 업무 처리 결과 코드입니다. 1은 정상 결과, 0은 실패 또는 무료 응답입니다. 서비스에 따라 2·3처럼 추가 코드를 쓰므로 같은 응답의 status·msg·error 필드도 함께 확인하세요.

- `data.hint` (string): 잘못된 model·speed·compact 값으로 실패했을 때 고치는 방법

- `data.retryable` (boolean): 502 실패에서 true면 잠시 후 같은 요청을 다시 보내도 됩니다. true/false로 오며, 값이 없으면 필드가 생략되거나 null일 수 있습니다. true = 이 필드가 나타내는 조건이 성립한 경우, false = 성립하지 않은 경우입니다. 두 값 모두 정상 응답에 올 수 있으며, 값이 없으면 필드가 생략되거나 null일 수 있습니다.

- `api` (object): API 호출 메타데이터입니다. 이번 요청의 서버 처리 성공 여부(api.success), 실제 차감 포인트(api.cost), 결제 기록 ID(api.pl_id)를 담습니다. 처리 시간(api.ms)은 응답에 포함된 경우에만 제공됩니다. 업무 결과는 data에서 확인합니다.

- `api.success` (boolean): API 서버가 이번 요청을 정상 처리했는지 여부입니다. true여도 업무 결과가 실패일 수 있으므로 data.success·data.status와 함께 판단합니다. 인증 실패·잘못된 입력·서버 오류 응답에서는 false입니다.

- `api.cost` (integer): 이번 호출에서 실제로 차감된 포인트입니다. 유료 성공 응답에서만 단가만큼 차감되며, 실패·무료 조회·같은 요청의 멱등 재전송은 0입니다. 화면의 표시 단가와 실제 차감액이 다를 수 있으므로 정산은 이 값을 기준으로 합니다.

- `api.ms` (integer): 서버가 요청을 받아 응답 본문을 만들기까지 걸린 처리 시간(밀리초)입니다. 네트워크 왕복 시간과 클라이언트 대기 시간은 포함되지 않습니다.

- `api.pl_id` (integer): 포인트 차감 기록 ID입니다. 차감이 발생한 호출에만 값이 있으며, 과금 내역을 문의할 때 이 번호를 사용합니다. 무과금 응답은 -1·null이거나 필드가 생략됩니다. null 허용.

## API 요청: POST /rest/llm/chat



### 입력

- `model` (string, 필수): 모델 id (llm_models Tool로 조회 가능, 예: openai/gpt-oss-120b)

- `content` (string, 조건부): 단발 입력 — 사용자 메시지 한 건만 보내는 간편 형태. messages 와 둘 중 하나는 필수

- `messages[0][role]` (string, 조건부): 각 메시지의 작성자. messages를 사용하면 각 항목에 필요합니다. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다. 가능한 값은 3가지입니다. system = 대화의 규칙·역할을 지정하는 시스템 메시지입니다. 사용자 메시지보다 먼저 적용됩니다. user = 사용자가 보낸 질문·지시 메시지입니다. assistant = 모델이 이전에 답한 메시지입니다. 대화 맥락을 이어 갈 때 넣습니다. 허용값: system, user, assistant

- `messages[0][content]` (string, 조건부): 각 메시지의 본문. 0부터 연속된 인덱스로 대화 순서를 전달합니다. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[1][role]` (string, 조건부): 두 번째 메시지 역할. 대화 순서대로 번호를 늘립니다. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[1][content]` (string, 조건부): 두 번째 메시지 내용. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[2][role]` (string, 조건부): 세 번째 메시지 역할. 마지막 메시지는 보통 이번에 묻는 user 메시지입니다.

- `messages[2][content]` (string, 조건부): 세 번째 메시지 내용. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[0][content][0][type]` (string, 조건부): 여러 종류의 콘텐츠를 담을 때 항목의 종류. 같은 메시지의 content 문자열과 함께 보낼 수 없습니다. 가능한 값은 3가지입니다. text = 텍스트 프롬프트만으로 결과를 만드는 값입니다. 이미지 입력 없이 문장 묘사만 사용합니다. image_url = 이미지 주소를 담은 콘텐츠 조각입니다. 텍스트와 함께 보낼 수 있습니다. input_audio = 음성 입력을 담은 콘텐츠 조각입니다. 지원 모델에서만 사용할 수 있습니다. 허용값: text, image_url, input_audio

- `messages[0][content][0][text]` (string, 조건부): 콘텐츠 항목이 text일 때 실제 텍스트입니다. 빈 문자열은 허용되지 않으며, 같은 메시지의 다른 콘텐츠와 순서대로 결합됩니다.

- `messages[0][content][1][type]` (string, 조건부): 두 번째 조각의 종류. 이미지면 image_url. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[0][content][1][image_url][url]` (string, 조건부): 이미지 주소. 로그인 없이 누구나 열 수 있는 https 주소를 넣습니다.

- `system` (string, 선택): system 프롬프트 (역할·페르소나·정책·배경지식). 미지정 시 기본 한국어 어시스턴트 프롬프트가 적용됩니다

- `compact[strategy]` (string, 선택): 대화 유지 방식. none은 전체 유지, sliding_window는 최근 대화쌍을 유지, relevance는 최근 대화쌍과 마지막 질문에 필요한 이전 대화쌍만 모델에 보냅니다. 가능한 값은 3가지입니다. none = 해당 옵션을 적용하지 않는 값입니다. 생략했을 때의 기본 동작과 같습니다. sliding_window = 최근 대화쌍만 유지하는 압축 방식입니다. 오래된 대화는 모델에 전달되지 않습니다. relevance = 검색어와의 관련도가 높은 순서로 정렬하는 값입니다. 기본 정렬로 가장 많이 쓰입니다. 기본값: none 허용값: none, sliding_window, relevance

- `compact[window_pairs]` (integer, 선택): sliding_window·relevance에서 모델에 보낼 대화쌍 수. 최소 1, 기본 10입니다. 기본값: 10

- `temperature` (number, 선택): 출력 다양성 0.0~2.0. 낮을수록 재현성, 높을수록 창의성 (미지정 시 모델 기본값)

- `max_tokens` (integer, 선택): 응답 최대 토큰. 미지정 시 모델 컨텍스트 기반 안전 상한으로 자동 설정, 명시한 값은 클램프 없이 그대로 적용

- `speed` (string, 선택): 응답 속도/추론 깊이 — 'fast'(얕게, 빠름) | 'medium' | 'slow'(깊게, 느림). 한글 '빠름'|'중간'|'느림' 허용. 추론 특화 모델에서 효과가 큽니다

- `stream` (boolean, 선택): true이면 SSE 응답을 받습니다. false이면 완성된 JSON 응답을 받습니다. 생성된 내용을 정리한 뒤 전송하며 토큰별 전송을 보장하지 않습니다. 기본값: false

- `messages` (array, 선택): OpenAI 형식 [{role, content}] 배열. role 은 'system'|'user'|'assistant'. content 와 둘 중 하나는 필수, 동시 지정 시 messages 우선. 멀티턴 대화는 응답의 compacted_messages 를 다음 턴에 그대로 전송

- `compact` (object, 선택): 히스토리 압축 옵션 { strategy: 'none'(기본) | 'sliding_window' | 'relevance', window_pairs: 유지할 user/assistant 페어 수 (기본 10, 최소 1) }. relevance 는 최근 대화와 함께 최신 질문에 필요한 이전 대화를 골라 남긴다. 긴 대화의 input 토큰 누적 방지

- `messages[0][name]` (string, 선택): 메시지 작성자의 이름. 사용하는 모델의 지원 여부를 확인하세요. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `messages[0][content][0][image_url][url]` (string, 조건부): type=image_url일 때 이미지 URL 또는 data URL. 모델이 이미지 입력을 지원해야 합니다.

- `messages[0][content][0][image_url][detail]` (string, 선택): 이미지 입력을 분석할 때 사용할 해상도 힌트입니다. auto는 모델 기본값, low는 빠르고 저렴, high는 작은 글자·세부 묘사에 유리합니다. 모델이 지원하지 않으면 무시됩니다. 가능한 값은 3가지입니다. auto = 서버·모델이 상황에 맞춰 자동으로 정하는 값입니다. 별도 지정이 필요 없습니다. low = 낮은 해상도·짧은 문맥처럼 비용과 속도를 우선하는 값입니다. high = 높은 해상도·긴 문맥처럼 정확도를 우선하는 값입니다. 토큰·처리 시간이 늘어납니다. 허용값: auto, low, high

- `messages[0][content][0][input_audio][data]` (string, 조건부): type=input_audio일 때 음성 Base64 값. 음성 입력 지원 모델에서만 사용합니다.

- `messages[0][content][0][input_audio][format]` (string, 조건부): 음성 입력 형식. 모델에서 지원하는 형식을 사용합니다. 문자열로 보내며, 생략하면 서버 기본값이 적용되거나 해당 조건이 해제됩니다.

- `message[role]` (string, 선택): 단일 메시지 객체의 역할. content 대신 객체로 보낼 때 사용합니다. 가능한 값은 3가지입니다. system = 대화의 규칙·역할을 지정하는 시스템 메시지입니다. 사용자 메시지보다 먼저 적용됩니다. user = 사용자가 보낸 질문·지시 메시지입니다. assistant = 모델이 이전에 답한 메시지입니다. 대화 맥락을 이어 갈 때 넣습니다. 허용값: system, user, assistant

- `message[content]` (string, 선택): 단일 메시지 방식에서 사용하는 본문입니다. 문자열 또는 콘텐츠 배열을 받으며, messages 배열과 동시에 보내지 마세요.



### 응답 명세

```json

{
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "model": {
          "type": "string",
          "description": "답변한 모델 ID"
        },
        "message": {
          "type": "object",
          "properties": {
            "role": {
              "type": "string",
              "description": "항상 assistant"
            },
            "content": {
              "type": "string",
              "description": "답변 본문"
            }
          }
        },
        "usage": {
          "type": "object",
          "properties": {
            "prompt_tokens": {
              "type": "integer",
              "description": "입력 토큰 수(입력 단가 적용)"
            },
            "completion_tokens": {
              "type": "integer",
              "description": "출력 토큰 수(출력 단가 적용)"
            },
            "total_tokens": {
              "type": "integer",
              "description": "입력 + 출력 토큰 수"
            }
          }
        },
        "compacted_messages": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "role": {
                "type": "string"
              },
              "content": {
                "type": "string"
              }
            }
          },
          "description": "다음 요청의 messages로 그대로 보낼 대화 기록. compact를 적용한 기록 끝에 이번 답변이 붙어 있습니다."
        },
        "ic_id": {
          "nullable": true
        },
        "result": {
          "type": "integer",
          "description": "1 성공, 0 실패"
        },
        "msg": {
          "type": "string",
          "description": "실패 사유. 성공하면 빈 문자열"
        },
        "success": {
          "type": "integer"
        },
        "hint": {
          "type": "string",
          "description": "잘못된 model·speed·compact 값으로 실패했을 때 고치는 방법"
        },
        "retryable": {
          "type": "boolean",
          "description": "502 실패에서 true면 잠시 후 같은 요청을 다시 보내도 됩니다."
        }
      }
    },
    "api": {
      "type": "object",
      "properties": {
        "success": {
          "type": "boolean"
        },
        "cost": {
          "type": "integer",
          "description": "이번 요청에서 차감된 포인트. 실패하면 0"
        },
        "ms": {
          "type": "integer",
          "description": "처리 시간(밀리초)"
        },
        "pl_id": {
          "type": "integer",
          "description": "포인트 사용 내역 번호",
          "nullable": true
        }
      }
    }
  }
}

```

### 정적 응답 예시

```json

{
  "data": {
    "model": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
    "message": {
      "role": "assistant",
      "content": "반갑습니다. 질문에 답하고 글을 정리해 드리는 AI 도우미입니다."
    },
    "usage": {
      "prompt_tokens": 62,
      "completion_tokens": 20,
      "total_tokens": 82
    },
    "compacted_messages": [
      {
        "role": "system",
        "content": "당신은 한국어 AI 어시스턴트입니다. 모든 답변은 한국어로 작성합니다. 사용자가 명시적으로 다른 언어를 요청한 경우에만 해당 언어로 응답합니다. 답변은 명확하고 간결하게, 필요한 경우 Markdown 서식(목록·코드 블록·굵은 글씨)을 활용합니다."
      },
      {
        "role": "user",
        "content": "한 문장으로 자기소개 해 줘."
      },
      {
        "role": "assistant",
        "content": "반갑습니다. 질문에 답하고 글을 정리해 드리는 AI 도우미입니다."
      }
    ],
    "ic_id": null,
    "result": 1,
    "msg": "",
    "success": 1
  },
  "api": {
    "success": true,
    "cost": 5,
    "ms": 482,
    "pl_id": 12345
  }
}

```

### curl

```curl

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string "model=${APICK_MODEL}" \
  --form-string 'content=한 문장으로 자기소개 해 줘.'

```

### Node.js (서버 ESM)

```javascript

const form = new FormData();
form.append("model", process.env.APICK_MODEL);
form.append("content", "한 문장으로 자기소개 해 줘.");
const response = await fetch("https://apick.app/rest/llm/chat", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.APICK_API_KEY },
  body: form,
  signal: AbortSignal.timeout(120_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
console.log(result);

```

### python

```python

import os
import requests
parts = [
    ("model", (None, os.environ["APICK_MODEL"])),
    ("content", (None, "한 문장으로 자기소개 해 줘.")),
]
response = requests.request("POST", "https://apick.app/rest/llm/chat",
    headers={"Authorization": "Bearer " + os.environ["APICK_API_KEY"]},
    files=parts,
    timeout=(10, 120))
response.raise_for_status()
result = response.json()
print(result)

```

### php

```php

<?php
$headers = ["Authorization: Bearer " . getenv("APICK_API_KEY")];
$form = [
    'model' => getenv('APICK_MODEL'),
    'content' => '한 문장으로 자기소개 해 줘.',
];
$curl = curl_init('https://apick.app/rest/llm/chat');
curl_setopt_array($curl, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $form,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120,
]);
$body = curl_exec($curl);
if ($body === false) { throw new RuntimeException(curl_error($curl)); }
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status >= 400) { throw new RuntimeException($body); }
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
print_r($result);

```

## 사용 예시 1. 지시문과 함께 단발 질문

`system`으로 답의 형식을 정하고 질문 한 건을 보냅니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'model=meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo' \
  --form-string 'system=답은 3개 이하의 글머리표로 짧게 작성하세요.' \
  --form-string 'content=재택근무 생산성을 높이는 방법을 알려 줘.' \
  --form-string 'temperature=0.3'

```

- 답변은 `data.message.content`, 사용 토큰은 `data.usage.prompt_tokens`·`completion_tokens`입니다.

- `data.result`가 0이면 `data.msg`와 `data.hint`를 보고 입력을 고칩니다.

## 사용 예시 2. 긴 대화를 최근 10쌍만 보내기

대화가 길어져 입력 토큰이 늘어날 때 `sliding_window`로 최근 대화만 모델에 보냅니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'model=meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo' \
  --form-string 'messages[0][role]=user' \
  --form-string 'messages[0][content]=다음 주 제주 여행 일정을 짜 줘. 2박 3일이야.' \
  --form-string 'messages[1][role]=assistant' \
  --form-string 'messages[1][content]=1일차 동쪽, 2일차 서쪽, 3일차 시내 위주로 제안드려요.' \
  --form-string 'messages[2][role]=user' \
  --form-string 'messages[2][content]=2일차에 비가 오면 어떻게 바꿀까?' \
  --form-string 'compact[strategy]=sliding_window' \
  --form-string 'compact[window_pairs]=10'

```

- `data.compacted_messages`를 다음 요청의 `messages`로 그대로 보냅니다. 오래된 대화는 이미 빠져 있습니다.

## 사용 예시 3. 이미지와 질문을 함께 보내기

멀티모달 모델에 이미지 주소와 질문을 한 메시지로 보냅니다. 이미지는 로그인 없이 열리는 https 주소여야 합니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'model=google/gemma-4-31B-it' \
  --form-string 'messages[0][role]=user' \
  --form-string 'messages[0][content][0][type]=text' \
  --form-string 'messages[0][content][0][text]=이 영수증의 합계 금액과 결제 일자만 알려 줘.' \
  --form-string 'messages[0][content][1][type]=image_url' \
  --form-string 'messages[0][content][1][image_url][url]=https://example.com/receipt.jpg'

```

- `multimodal: true`가 아닌 모델에 보내면 이미지를 읽지 못합니다. 모델 카탈로그에서 먼저 확인합니다.

## 사용 예시 4. SSE로 받기

이미 SSE 클라이언트를 쓰는 환경에서 `stream=true`로 받습니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'model=meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo' \
  --form-string 'content=바닷가 마을을 배경으로 짧은 이야기를 써 줘.' \
  --form-string 'stream=true' \
  --form-string 'speed=fast' \
  --no-buffer

```

- 첫 `data` 이벤트의 `choices[0].delta.content`에 답변 전체가 옵니다.

- `event: done`의 `cost`가 차감 포인트, `compacted_messages`가 다음 턴 기록입니다.

## 사용 예시 5. 복잡한 판단을 깊게 추론

정책 해석·계산처럼 단계적 추론이 필요하면 추론 모델에 `speed=slow`를 보냅니다. 응답까지 몇 분이 걸릴 수 있습니다.

```bash

curl --fail-with-body --request POST 'https://apick.app/rest/llm/chat' \
  --header "Authorization: Bearer $APICK_API_KEY" \
  --form-string 'model=deepseek-ai/DeepSeek-V4-Pro' \
  --form-string 'content=연차 15일 중 6일을 썼고 남은 연차의 절반을 다음 해로 이월할 수 있다면, 이월 가능한 일수와 계산 과정을 알려 줘.' \
  --form-string 'speed=slow' \
  --form-string 'max_tokens=4096'

```

- `data.usage.completion_tokens`가 커질수록 비용이 늘어납니다. `api.cost`로 실제 차감액을 확인합니다.

## 코드·오류

## 상세 기능·요금

상황별 가이드 목적가이드 한 번 묻고 답 받기단발 호출 가이드 여러 턴 대화 이어가기멀티챗 가이드 말투·역할이 정해진 챗봇챗봇 구축 가이드 업무 규칙을 지키는 AI 비서에이전트 구축 가이드 모델 ID·단가 확인모델 카탈로그 대화 기록과 compact 대화 기록은 저장되지 않습니다. 앱이 기록을 보관하고, 매 요청에 지금까지의 메시지를 messages로 보냅니다. 응답의 data.compacted_messages를 다음 요청의 messages로 그대로 쓰고, 끝에 새 user 메시지만 붙이세요. 받은 답변을 직접 이어 붙이면 compact가 적용된 기록과 어긋납니다. compacted_messages의 맨 앞에는 system 메시지가 있습니다. system을 보내지 않았다면 기본 한국어 지시문이 들어 있습니다. sliding_window: system 메시지는 모두 남기고, 질문·답변 쌍은 최근 window_pairs개만 모델에 보냅니다. compacted_messages도 같은 범위로 줄어듭니다. relevance: 최근 2쌍과, 마지막 질문에 답하는 데 필요한 이전 쌍을 골라 window_pairs개 이내로 모델에 보냅니다. compacted_messages에는 다음 질문에서 다시 고를 수 있도록 최근 50쌍까지 남습니다. 요약해서 줄이는 방식은 없습니다. 아주 긴 대화는 앞부분을 대화 API로 따로 요약한 뒤 그 결과를 system에 넣어 대체하세요. SSE 스트림 받기 stream=true로 보내면 아래 순서로 이벤트가 옵니다. 답변 전체가 첫 data 이벤트 하나에 담겨 오므로, 글자 단위로 나눠 받는 용도가 아니라 SSE 클라이언트로 받아야 하는 환경에서 씁니다. 순서이벤트내용 1data: {...}choices[0].delta.content에 답변 본문 전체가 들어 있습니다. 2event: donemodel, usage, cost(차감 포인트), pl_id, compacted_messages가 들어 있습니다. 이 이벤트를 받으면 연결이 닫힙니다. 실패 시event: errormsg에 실패 사유가 들어 있습니다. done을 받지 못했다면 차감 여부를 포인트 사용 내역에서 확인한 뒤 다시 요청하세요. data: {"choices":[{"delta":{"content":"옛날 어느 바닷가 마을에..."}}]} event: done data: {"model":"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo","usage":{"prompt_tokens":64,"completion_tokens":512,"total_tokens":576},"cost":5,"pl_id":12345,"compacted_messages":[...]} 요금 입력·출력 토큰 수 × 모델별 1M 토큰당 단가로 정산합니다. 요청 합계는 포인트 단위로 올림합니다. 2026-11-06부터 요청당 기본요금 5P가 최소액입니다(그 전에는 최소 1P). relevance에서 이전 대화를 고르는 데 쓴 사용량도 같은 요청에 합산됩니다. 모델별 단가는 모델 카탈로그의 price에서 확인합니다.

## 상세 요청

MethodURL POST https://apick.app/rest/llm/chat 배열·객체는 항목 이름에 위치를 붙여 나눠 보냅니다. 예를 들어 세 번째 메시지는 messages[2][role], messages[2][content]입니다. 번호는 0부터 빠짐없이 이어서 씁니다. 표에 없는 top_p, seed, stop, tools, response_format 같은 값은 보내도 결과에 반영되지 않습니다. form-data 전체 예제 보기

## 상세 응답

필드타입설명 data.modelString답변한 모델 ID data.message.roleString항상 assistant data.message.contentString답변 본문 data.usage.prompt_tokensInteger입력 토큰 수(입력 단가 적용) data.usage.completion_tokensInteger출력 토큰 수(출력 단가 적용) data.usage.total_tokensInteger입력 + 출력 토큰 수 data.compacted_messagesArray다음 요청의 messages로 그대로 보낼 대화 기록. compact를 적용한 기록 끝에 이번 답변이 붙어 있습니다. data.resultInteger1 성공, 0 실패 data.msgString실패 사유. 성공하면 빈 문자열 data.hintString잘못된 model·speed·compact 값으로 실패했을 때 고치는 방법 data.retryableBoolean502 실패에서 true면 잠시 후 같은 요청을 다시 보내도 됩니다. api.costInteger이번 요청에서 차감된 포인트. 실패하면 0 api.msInteger처리 시간(밀리초) api.pl_idInteger/null포인트 사용 내역 번호 { "data": { "model": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", "message": { "role": "assistant", "content": "반갑습니다. 질문에 답하고 글을 정리해 드리는 AI 도우미입니다." }, "usage": { "prompt_tokens": 62, "completion_tokens": 20, "total_tokens": 82 }, "compacted_messages": [ { "role": "system", "content": "당신은 한국어 AI 어시스턴트입니다. 모든 답변은 한국어로 작성합니다. 사용자가 명시적으로 다른 언어를 요청한 경우에만 해당 언어로 응답합니다. 답변은 명확하고 간결하게, 필요한 경우 Markdown 서식(목록·코드 블록·굵은 글씨)을 활용합니다." }, { "role": "user", "content": "한 문장으로 자기소개 해 줘." }, { "role": "assistant", "content": "반갑습니다. 질문에 답하고 글을 정리해 드리는 AI 도우미입니다." } ], "ic_id": null, "result": 1, "msg": "", "success": 1 }, "api": { "success": true, "cost": 5, "ms": 482, "pl_id": 12345 } }

## 상세 코드·정책

오류 코드 HTTPdata.msg대처 400model requiredmodel을 보내세요. 400unsupported model (text-generation 카탈로그 외)모델 카탈로그의 id를 그대로 쓰세요. 400content/message/messages requiredcontent 또는 messages를 보내세요. 400unsupported speedfast·medium·slow(또는 한글 값)만 씁니다. 400unknown compact.strategynone·sliding_window·relevance만 씁니다. 402잔액 부족 (최소 1포인트 필요)포인트를 충전한 뒤 다시 요청하세요. 402payment failed after call포인트 차감을 마치지 못했습니다. 잔액을 확인한 뒤 다시 요청하세요. 500서비스 설정을 확인할 수 없습니다.잠시 후 다시 시도하고, 계속되면 문의하세요. 502외부 처리 서비스 응답 오류data.retryable이 true면 1~2초 뒤 한 번만 다시 보내세요. 과금되지 않습니다. 400·402·500·502 실패는 모두 api.cost가 0입니다. 같은 요청을 무한히 반복하지 말고, 400·402는 입력이나 잔액을 고친 뒤 보내세요.
