# LLM API

> Endue API 키로 내 코드에서 모델을 바로 부릅니다. 쓰던 OpenAI·Anthropic SDK 를 그대로 쓰고, 호출마다 크레딧에서 차감됩니다.

**LLM API** 는 내 코드가 Endue API 키로 모델을 바로 부르게 합니다. 요청 형식은 OpenAI·Anthropic API 와 같고, 호출마다 크레딧에서 비용이 빠집니다.

## 언제 쓰는가

에이전트가 아니라 모델이 필요할 때입니다. 내 앱 안에서 쓰는 응답 생성, 이미 OpenAI·Anthropic API 를 부르고 있는 코드, 그리고 Claude Code 가 그렇습니다. base URL 과 키만 바꾸면 나머지 코드는 그대로입니다.

프롬프트·메모리·도구·커넥터를 가진 에이전트에게 일을 맡기려면 [에이전트 API](/ko/docs/build/agent-api/)를 쓰세요.

## 첫 호출

<Steps>

1. **계정 전체 키를 발급합니다.** **설정 → 계정 → API 키**에서 만들고, 보일 때 복사하세요. 키는 한 번만 보여줍니다. 에이전트의 API 섹션에서 만든 키는 그 에이전트로 제한돼 모델을 직접 부를 수 없습니다.

2. **키를 코드에 적지 마세요.** 환경 변수(예: `ENDUE_API_KEY`)에 둡니다.

3. **SDK 를 Endue 로 향하게 합니다.** 아래 base URL 을 넣고, [모델 목록](#모델과-가격)에 있는 모델을 부릅니다.

   ```
   https://platform.endue.ai/api/v1/llm
   ```

</Steps>

<Tabs syncKey="llm-api-lang">
  <TabItem label="Python">
    ```python
    import os
    from openai import OpenAI

    client = OpenAI(base_url="https://platform.endue.ai/api/v1/llm", api_key=os.environ["ENDUE_API_KEY"])
    res = client.chat.completions.create(
        model="openai/gpt-5.4",
        messages=[{"role": "user", "content": "안녕하세요"}],
    )
    print(res.choices[0].message.content)
    ```
  </TabItem>
  <TabItem label="Node.js">
    ```js
    import OpenAI from 'openai';

    const client = new OpenAI({ baseURL: 'https://platform.endue.ai/api/v1/llm', apiKey: process.env.ENDUE_API_KEY });
    const res = await client.chat.completions.create({
      model: 'openai/gpt-5.4',
      messages: [{ role: 'user', content: '안녕하세요' }],
    });
    console.log(res.choices[0].message.content);
    ```
  </TabItem>
  <TabItem label="curl">
    ```bash
    curl https://platform.endue.ai/api/v1/llm/chat/completions \
      -H "Authorization: Bearer $ENDUE_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"model":"openai/gpt-5.4","messages":[{"role":"user","content":"안녕하세요"}]}'
    ```
  </TabItem>
  <TabItem label="Anthropic SDK">
    ```python
    import os
    import anthropic

    client = anthropic.Anthropic(base_url="https://platform.endue.ai/api/v1/llm", api_key=os.environ["ENDUE_API_KEY"])
    msg = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": "안녕하세요"}],
    )
    print(msg.content[0].text)
    ```
  </TabItem>
  <TabItem label="Claude Code">
    ```bash
    export ANTHROPIC_BASE_URL=https://platform.endue.ai/api/v1/llm
    export ANTHROPIC_API_KEY=$ENDUE_API_KEY
    claude
    ```
  </TabItem>
</Tabs>

**설정 → 계정 → LLM API** 에도 같은 base URL 과 예시가 있어 바로 복사할 수 있습니다.

## 모델과 가격

`GET https://platform.endue.ai/api/v1/llm/models` 는 부를 수 있는 모델 전부를 컨텍스트 길이·가격과 함께 돌려줍니다. 읽는 데는 키가 필요 없습니다.

- **모델 id** 는 `openai/gpt-5.4`, `x-ai/grok-4.6` 처럼 제공사/모델 꼴입니다.
- **가격**은 토큰당 크레딧이고 소수 문자열입니다. 입력은 `prompt`, 출력은 `completion`, 캐시된 입력을 할인하는 모델은 `input_cache_read` 에 적힙니다. 1 크레딧은 1 미국 달러입니다.
- 아주 긴 프롬프트에 더 비싼 값을 받는 모델이 있습니다. 그 가격은 `overrides` 에, 적용이 시작되는 프롬프트 길이와 함께 적힙니다.

같은 모델을 [모델 페이지](/models)에서도 둘러볼 수 있습니다.

## 스트리밍

`"stream": true` 를 넣으면 OpenAI 청크 형식의 SSE 로 답이 흘러오고 `data: [DONE]` 으로 끝납니다. `[DONE]` 바로 앞 청크의 `usage` 에 이 호출의 비용이 들어 있습니다.

## 과금 방식

<Steps>

1. **모델을 부르기 전에** 이 호출이 가장 많이 들 수 있는 만큼, 즉 프롬프트와 `max_tokens` 만큼의 출력 비용을 크레딧에서 잡아 둡니다. 잔액이 그보다 적으면 모델을 부르지 않고 `402` 를 돌려줍니다.

2. **호출이 끝나면** 실제로 든 비용만 차감하고, 잡아 둔 나머지는 잔액으로 돌려줍니다.

3. **응답에 차감액이 적혀 옵니다.** `usage.cost` 가 이 호출로 빠진 크레딧이고, `X-Endue-Request-Id` 헤더가 문의할 때 쓸 호출 식별자입니다.

</Steps>

`max_tokens` 를 빼고 부르면서 잔액이 모델의 최대 출력 길이를 감당하지 못하면, 잔액이 감당하는 길이로 `max_tokens` 를 낮춰 호출합니다. 그 길이가 1,024 토큰보다 짧으면 `402` 입니다.

LLM API 호출은 **구매·프로모션 크레딧**에서만 빠집니다. 요금제의 사용 한도는 에이전트용이라 여기서는 쓰이지 않습니다. 호출 내역은 [사용량 대시보드](/ko/docs/account/usage/#출처)의 **출처** 탭에 **LLM API** 로 나옵니다.

## Anthropic 형식과 Claude Code

같은 base URL 이 Anthropic Messages 형식도 받습니다. Anthropic SDK 와 Claude Code 는 base URL 뒤에 `/v1/messages` 를 스스로 붙이므로, 위 탭의 두 줄이 설정의 전부입니다.

- 키는 `x-api-key` 로 보내도 되고 `Authorization: Bearer` 로 보내도 됩니다.
- Claude 모델 이름은 Anthropic 에 쓰던 그대로 됩니다 — `claude-sonnet-4-5`, 또는 `claude-sonnet-4-5-20250929` 처럼 날짜가 붙은 이름. 그 모델이 모델 목록에 있어야 합니다. 모델 목록의 id 도 그대로 되며, Claude 가 아닌 모델도 부를 수 있습니다.
- 스트리밍은 Anthropic 이벤트 형식, 오류는 Anthropic 오류 형식으로 옵니다.
- `/v1/messages/count_tokens` 는 입력 토큰의 추정치를 돌려줍니다. 과금되지 않으며, 토크나이저로 센 정확한 값이 아니라 근사치입니다.

## 오류

오류는 부른 형식의 모양으로 옵니다. OpenAI 형식은 `{"error": {…}}`, Anthropic 형식은 `{"type": "error", "error": {…}}` 입니다.

| 상태 | 무슨 일인가 | 할 일 |
| --- | --- | --- |
| `400` | 요청 형식이 잘못됐거나, `n` 이 1 보다 크거나, 모델이 입력을 거부했습니다 | 메시지가 가리키는 곳을 고칩니다 |
| `401` | 키가 없거나, 해지됐거나, 틀렸습니다 | 키와 보내는 방식을 확인합니다 |
| `402` | 크레딧 잔액이 이 호출을 감당하지 못합니다(`insufficient_credits`, Anthropic 형식은 `billing_error`) | 크레딧을 사거나 `max_tokens` 를 낮춥니다 |
| `403` | 키가 에이전트 하나로 제한돼 있습니다 | 계정 전체 키를 발급합니다 |
| `404` | 모델 목록에 없는 모델입니다 | `/models` 의 id 를 씁니다 |
| `429` | 요청이 너무 많습니다 | `Retry-After` 의 초만큼 기다립니다 |
| `502` | 모델 제공사가 실패했습니다 | 다시 시도합니다 |
| `503` | 결제나 모델 목록을 잠시 쓸 수 없습니다. 모델은 불리지 않았고 차감도 없습니다 | 잠시 뒤 다시 시도합니다 |

## 한계

- 모델 목록에 있는 모델만 부를 수 있습니다.
- 지원 형식은 OpenAI Chat Completions 와 Anthropic Messages 둘입니다. 임베딩·이미지·음성·Responses 엔드포인트는 없습니다.
- `n` 은 1 이어야 합니다.
- 표준 요청 밖의 필드는 무시합니다. 다른 모델로 넘어가는 폴백 목록, 제공사 라우팅, 플러그인 같은 것들입니다. Anthropic 형식에서 웹 검색 같은 서버 도구는 거부하고, `top_k` 는 무시합니다.
- 요금제 사용 한도는 쓰이지 않습니다. 구매·프로모션 크레딧이 있어야 호출됩니다.
- 에이전트 하나로 제한된 키로는 모델을 부를 수 없습니다.
- 분당 100회까지이며 키 단위와 계정 단위로 함께 셉니다. 요청 본문은 8 MB 까지입니다.
- `count_tokens` 는 추정치입니다.

## 관련

<CardGrid>
  <LinkCard
    title="에이전트 API"
    href="/ko/docs/build/agent-api/"
    description="모델 대신, 프롬프트·메모리·도구를 가진 에이전트를 부릅니다."
  />
  <LinkCard
    title="사용량 대시보드"
    href="/ko/docs/account/usage/"
    description="출처 탭에서 LLM API 지출을 에이전트 지출과 나란히 봅니다."
  />
  <LinkCard
    title="모델 고르기"
    href="/ko/docs/build/models/"
    description="모델이 어떻게 다르고, 서로 비해 얼마나 드는지."
  />
  <LinkCard
    title="보안과 권한"
    href="/ko/docs/account/security/"
    description="키가 어디까지 닿는지, 어떻게 거둬들이는지."
  />
</CardGrid>
