# GPT-6 Astra — /chat/completions

GPT-6 Astra(OpenAI) 채팅 API로, GPT-6 제품군의 플래그십입니다. 컨텍스트 창은 1,050,000 토큰, 요청당 출력은 최대 128,000 토큰이며, 사고 깊이를 low부터 max까지 다섯 단계로 조절할 수 있습니다. 이미지 입력, 도구 호출, JSON 출력을 지원하고, OpenAI SDK와 호환되며 /v1/responses로도 호출할 수 있습니다.

**엔드포인트:** `POST https://nezhagate.com/v1/chat/completions`

## 빠른 시작

두 단계면 됩니다: 요청 보내기 → 스트리밍으로 답변 받기. YOUR_API_KEY를 내 키로 바꾸면 아래 명령을 그대로 실행할 수 있습니다. 엔드포인트가 OpenAI Chat Completions와 같으므로 기존 OpenAI 코드는 `base_url`과 `model`만 바꾸면 됩니다.

**1단계 · 요청 보내기**

```
curl https://nezhagate.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "messages": [{"role": "user", "content": "광합성을 한 문장으로 설명해 줘"}]}'
```

응답(HTTP 200)

```
{
  "id": "chatcmpl-7f3c9a1e2b4d6f8a",
  "object": "chat.completion",
  "created": 1791281400,
  "model": "gpt-6-astra",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "광합성은 식물이 햇빛을 이용해 이산화탄소와 물을 당으로 바꾸고 산소를 내보내는 과정입니다.",
        "reasoning_content": "..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 18,
    "completion_tokens": 186,
    "total_tokens": 204,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 144}
  }
}
```

`message.content`는 답변이고 `message.reasoning_content`는 사고 과정입니다. `usage`는 이 요청에 과금되는 토큰 수이며, 사고 토큰은 `completion_tokens`에 포함되어 출력 요금으로 과금됩니다.

**2단계 · 스트리밍으로 받기(권장)**

```
curl -N https://nezhagate.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "stream": true, "messages": [{"role": "user", "content": "광합성을 한 문장으로 설명해 줘"}]}'
```

스트림은 표준 SSE입니다. 각 청크의 본문은 `choices[0].delta.content`에 담기고, 마지막 청크에는 `usage`가 담기며, 스트림은 `data: [DONE]`으로 끝납니다. 답변이 길거나 모델이 먼저 생각해야 할 때는 스트리밍을 쓰세요. 비스트리밍 요청은 약 10분이 지나면 연결이 끊깁니다.

**Python(OpenAI SDK)**

```
from openai import OpenAI

client = OpenAI(base_url="https://nezhagate.com/v1", api_key="YOUR_API_KEY")

# 1. 질문 하나에 답변 하나
resp = client.chat.completions.create(
    model="gpt-6-astra",
    messages=[{"role": "user", "content": "광합성을 한 문장으로 설명해 줘"}],
)
print(resp.choices[0].message.content)

# 2. 스트리밍
stream = client.chat.completions.create(
    model="gpt-6-astra",
    messages=[{"role": "user", "content": "광합성을 한 문장으로 설명해 줘"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

## 인증
```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

## 사양 한눈에 보기

| 컨텍스트 창 | 1,050,000 토큰 |
| --- | --- |
| 요청당 최대 출력 | 128,000 토큰 |
| 입력 | 텍스트, 이미지 |
| 사고 | `reasoning_effort`에 따라 생각함(생략하면 medium), 사고 요약은 `reasoning_content`로 반환 |
| 도구 호출 | 지원(OpenAI `tools` 형식) |
| JSON 출력 | 지원(`response_format`) |
| 웹 검색 | 지원(`web_search: true`, 검색 자체는 무료) |
| 엔드포인트 | /v1/chat/completions · /v1/responses |
| 스트리밍 | 지원(`stream: true`, SSE) |
| 과금 방식 | 토큰 단위: 입력, 출력(사고 포함), 캐시 적중에 각각 요금 적용, 실패하면 과금되지 않음 |

## 요청 파라미터

`POST /v1/chat/completions`의 요청 본문(JSON)이며, OpenAI Chat Completions와 같습니다. 자주 쓰는 파라미터와 이 모델에서의 실제 동작은 다음과 같습니다:

| 파라미터 | 타입 | 필수 | 설명 |
| --- | --- | --- | --- |
| model | string | 예 | 모델 ID: `gpt-6-astra`. |
| messages | array | 예 | 대화 메시지 배열입니다. 각 메시지에는 `role`(`system`, `user`, `assistant`, `tool` 중 하나)과 `content`가 있습니다. `content`는 문자열이거나 `text`와 `image_url` 파트로 이루어진 배열입니다(이미지 입력, 아래 참고). 여러 턴에 걸친 대화는 이전 메시지를 순서대로 모두 보내세요. |
| stream | boolean | 아니오 | `true`면 SSE로 스트리밍하며, 마지막 청크에 `usage`가 담깁니다. 기본값은 `false`입니다. |
| max_tokens | integer | 아니오 | 이 모델은 출력 상한을 받지 않습니다. `max_tokens` / `max_completion_tokens`는 무시됩니다(오류 없음). 짧은 답변이 필요하면 프롬프트에서 요청하세요. |
| temperature / top_p | number | 아니오 | 이 모델은 샘플링 파라미터를 받지 않으며, 보내도 무시됩니다(오류 없음). |
| reasoning_effort | string | 아니오 | 사고 깊이: low / medium / high / xhigh / max. 기본값은 medium입니다. 단계가 높을수록 더 오래, 더 신중하게 생각하지만 응답이 느려지고 출력 토큰도 늘어납니다. `gpt-6-astra-high`처럼 단계를 모델 ID에 넣어도 됩니다. |
| tools / tool_choice | array / string | 아니오 | OpenAI 표준 형식의 함수 호출입니다. 모델이 함수를 호출할 때는 `finish_reason: "tool_calls"`와 함께 `tool_calls`를 돌려줍니다. 자세한 내용은 아래를 보세요. |
| response_format | object | 아니오 | `{"type": "json_object"}`를 보내면 모델이 올바른 JSON만 출력합니다. 프롬프트에도 JSON으로 답하라는 것과 필요한 필드를 적어 주세요. |
| web_search | boolean | 아니오 | `true`면 먼저 웹 검색을 하고 그 결과를 참고 자료로 모델에 넘깁니다. 자세한 내용은 아래를 보세요. |

`frequency_penalty`와 `presence_penalty`도 무시됩니다. 그 밖의 OpenAI 파라미터는 보낸 그대로 모델에 전달됩니다.

## 가격

토큰 단위로 과금하며, 아래 요금(100만 토큰당)은 실시간으로 반영됩니다. 성공한 요청의 실제 사용량만 과금하고, 실패, 시간 초과, 거부된 요청은 과금하지 않습니다. 1크레딧 = $0.005.

| 종류 | 100만 토큰당 가격(USD) | 100만 토큰당 크레딧 |
| --- | --- | --- |
| 입력 | $3.00 | 600 |
| 출력(사고 포함) | $15.00 | 3000 |
| 캐시 적중 | $0.30 | 60 |

예를 들어 입력 2,000 토큰, 출력 1,000 토큰(사고 포함)인 요청 한 건은 약 $0.021입니다.

## 사고(Thinking)

`reasoning_effort`에는 low / medium / high / xhigh / max를 쓸 수 있으며, 생략하면 게이트웨이가 medium으로 요청합니다. 단계가 높을수록 더 오래 생각해 더 안정적으로 답하지만, 응답이 느려지고 출력 토큰도 늘어납니다. 간단한 질문에는 low로 충분합니다.

사고 요약은 `message.reasoning_content`로 반환됩니다(스트리밍에서는 `delta.reasoning_content`). 단계를 모델 ID에 넣어 `gpt-6-astra-low`, `gpt-6-astra-high`, `gpt-6-astra-xhigh`처럼 써도 효과가 같으며, 과금은 `gpt-6-astra` 기준입니다.

/v1/responses에서는 사고 깊이를 `reasoning.effort`에 넣으며, 사고 요약은 `reasoning.summary`를 직접 설정했을 때만 반환됩니다(게이트웨이가 대신 넣지 않습니다).

사고 토큰은 `usage.completion_tokens`에 포함되어 출력 요금으로 과금됩니다(일부 모델은 `completion_tokens_details.reasoning_tokens`에 따로 표시합니다).

## 프롬프트 캐싱

별도의 파라미터는 필요 없습니다. 반복되는 긴 접두어(같은 시스템 프롬프트, 대화의 앞부분)는 모델 제공사가 자동으로 캐시할 수 있으며, 캐시에 적중한 부분은 더 낮은 캐시 요금으로 과금됩니다. 캐시 여부와 적중량은 모델 제공사가 정합니다. 바뀌지 않는 내용을 메시지 맨 앞에 두면 적중률을 높일 수 있습니다.

캐시에 적중한 토큰 수는 `usage.prompt_tokens_details.cached_tokens`로 반환되며, 이 부분은 캐시 적중 요금으로, 나머지 입력은 입력 요금으로 과금됩니다.

## 이미지 입력

`content` 배열에 `image_url` 파트를 넣으세요. base64 data URI(`data:image/png;base64,...`)를 권장하며, 이 방식은 모든 회선에서 읽을 수 있습니다. 공개 이미지 링크는 회선이 직접 내려받아야 해서 일부 회선에서는 가져오지 못하거나 시간이 초과될 수 있습니다. 이미지는 모델 제공사의 규칙에 따라 입력 토큰으로 환산됩니다.

```
curl https://nezhagate.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "messages": [{"role": "user", "content": [{"type": "text", "text": "이 이미지에 무엇이 있는지 알려 줘"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBORw0KGgo..."}}]}]}'
```

## 도구 호출(Function Calling)

`tools`에 JSON Schema로 함수를 정의하세요. 모델이 함수를 호출하기로 하면 `finish_reason: "tool_calls"`를 돌려주며, `message.tool_calls`에 함수 이름과 인자(JSON 문자열)가 담깁니다.

```
curl https://nezhagate.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "messages": [{"role": "user", "content": "지금 상하이 날씨를 알려 줘"}], "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Current weather of a city", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}}]}'
```

함수를 실행한 뒤 그 결과를 `role: "tool"` 메시지로(해당 `tool_call_id`와 함께) 대화에 덧붙여 다시 요청하면, 모델이 이를 바탕으로 최종 답변을 줍니다. `tool_choice`에는 `auto`, `none`, `required` 또는 특정 함수를 지정할 수 있습니다.

## Responses API(/v1/responses)

이 모델은 OpenAI Responses API로도 호출할 수 있습니다. Codex 같은 도구가 쓰는 바로 그 API입니다. 요청과 응답은 OpenAI Responses 형식을 따르며, 입력은 `input`에, 사고 깊이는 `reasoning.effort`에 넣습니다.

```
curl https://nezhagate.com/v1/responses \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "input": "광합성을 한 문장으로 설명해 줘", "reasoning": {"effort": "medium", "summary": "auto"}}'
```

이 엔드포인트는 기본 사고 단계를 대신 넣지 않으며 사고 요약도 자동으로 돌려주지 않습니다. 요약이 필요하면 위 예시처럼 `"summary": "auto"`를 보내세요. 과금은 채팅 엔드포인트와 같으며, 웹 검색은 /v1/chat/completions에서만 제공됩니다.

## 웹 검색

요청에 `"web_search": true`를 넣으세요(또는 `tools`에 `{"type": "web_search"}` 항목을 넣어도 됩니다). 게이트웨이가 먼저 대화 내용을 바탕으로 실시간 웹 검색을 하고 최대 5개의 결과를 링크와 함께 참고 자료로 모델에 넘기면, 모델이 이를 바탕으로 답하면서 출처를 표시합니다. 검색 자체는 무료이며, 참고 자료는 입력 토큰으로 과금됩니다.

```
curl https://nezhagate.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-6-astra", "web_search": true, "messages": [{"role": "user", "content": "오늘 주요 기술 뉴스를 알려 줘"}]}'
```

## 회선과 안정성

- 모든 모델은 여러 회선으로 제공됩니다. 한 회선에서 오류나 시간 초과가 나거나 회선이 가득 차면, 게이트웨이는 응답을 돌려주기 시작하기 전에 자동으로 다음 회선으로 넘어갑니다. 따로 재시도할 필요가 없고, 두 번 과금되지도 않습니다.

- 스트리밍은 출력을 시작한 뒤에는 회선을 바꾸지 않습니다. 중간에 끊기면 끊기기 전까지 생성된 사용량만큼 과금됩니다([과금과 환불](https://nezhagate.com/ko/docs/guide/billing) 참고).

- 모든 회선이 가득 차면 게이트웨이가 `Retry-After`와 함께 429를 돌려줍니다. 그 초만큼 기다린 뒤 다시 시도하세요. 실패한 요청은 과금되지 않습니다. 모델별 상태는 [서비스 상태](https://nezhagate.com/ko/status)에서 볼 수 있습니다.

## 오류와 환불

오류는 `error` 객체(`message`, `type`, `code`, `param`)로 돌아옵니다. HTTP 상태 코드와 `code`로 판단하고, `message` 문구로는 판단하지 마세요. 실패한 요청은 과금되지 않으며, 전체 목록은 [오류 코드](https://nezhagate.com/ko/docs/guide/errors)에 있습니다.

| HTTP | code | 원인 | 조치 |
| --- | --- | --- | --- |
| 400 | invalid_messages / invalid_role / invalid_max_tokens | 채팅 요청의 `messages`가 없거나 비어 있거나 형식이 잘못되었거나, `role`이 허용된 값이 아니거나, `max_tokens`가 양의 정수가 아닙니다. 문제가 된 필드는 `param`에 표시됩니다. | `param`이 가리키는 필드를 고치세요. |
| 400 | model_not_found | 모델 ID의 철자가 틀렸거나, `model`이 없거나, 이 엔드포인트에서 쓸 수 없는 모델입니다(예: 이미지 엔드포인트에 채팅 모델을 지정한 경우). | `GET /v1/models` 또는 [API 레퍼런스](https://nezhagate.com/ko/docs/api)에 있는 모델 ID를 쓰세요. |
| 400 | max_tokens_too_small | 추론 모델이 `max_tokens`를 모두 사고에 써서 답변을 쓰지 못했습니다(비스트리밍 채팅). | `max_tokens`를 늘린 뒤 다시 시도하세요. |
| 4xx | invalid_request | 모델 제공사가 요청을 거부했습니다(예: 컨텍스트가 너무 길거나 지원하지 않는 파라미터). 상태 코드와 `message`는 모델 제공사가 보낸 그대로 전달되며, `code`는 모델 제공사가 준 값입니다. | `message`에 적힌 대로 요청을 고치세요. |
| 401 | invalid_api_key | 키가 없거나, 삭제되었거나, 비활성화되었습니다. 계정이 비활성화된 경우에도 나옵니다. | 콘솔의 「API Keys」 페이지에서 이 키를 확인하세요. |
| 402 | insufficient_quota | 이 요청의 크레딧을 예약하기에 잔액이 부족합니다. 게이트웨이는 요청에 들 수 있는 최대 비용을 먼저 예약하므로, 동시 호출이 몰릴 때도 이 오류가 날 수 있습니다. | 동시 호출이 몰린 경우라면 몇 초 기다린 뒤 다시 시도하고, 그렇지 않으면 충전하세요. |
| 403 | permission_denied | 이 모델이 키의 모델 허용 목록에 없습니다. | 허용 목록에 있는 모델을 쓰거나, 콘솔에서 허용 목록을 수정하세요. |
| 429 | rate_limit_exceeded | 이 키에 설정한 분당 요청 수를 넘었습니다(최근 60초 기준). `Retry-After` 헤더는 붙지 않습니다. | 몇 초 기다린 뒤 다시 시도하거나, 콘솔에서 이 키의 한도를 올리세요. |
| 429 | rate_limit_exceeded | 이 모델의 모든 회선이 가득 차서 요청을 보내지 못했습니다. 채팅 엔드포인트에서만 나오며, 이미지와 영상 작업은 거절되지 않고 대기열에서 기다립니다. OpenAI 호환 엔드포인트는 `Retry-After`를 붙입니다. | `Retry-After`의 초만큼 기다린 뒤 다시 시도하세요. |
| 502 | upstream_timeout | 회선이 시간 초과되었습니다. 첫 토큰이 너무 늦게 오는 경우도 포함됩니다. | 다시 시도하세요. 긴 답변에는 `stream: true`를 쓰세요. |
| 502 | upstream_unavailable | 회선에 오류가 났거나 잠시 쓸 수 없습니다. | 잠시 후 다시 시도하세요. |
| 502 | upstream_busy | 모델 제공사가 요청 빈도를 제한하고 있습니다. 모델 제공사의 429는 그대로 전달되지 않고 이 502로 바뀌어 돌아옵니다. | 잠시 후 다시 시도하세요. |
| 502 | empty_completion | 모델 제공사가 빈 내용을 돌려주었습니다. 요청 내용에 대한 판정이 아닙니다. | 다시 시도하세요. |
| 503 | model_maintenance | 모델이 점검 중이라 요청을 받지 않습니다. 점검 중에는 다른 모델이 대신 답변하지도 않습니다. | 점검이 끝나면 다시 시도하세요. 진행 상황은 [서비스 상태](https://nezhagate.com/ko/status)에서 볼 수 있습니다. |

스트리밍이 출력을 시작한 뒤 실패하면 상태 코드는 바뀌지 않습니다. 오류는 `error`가 담긴 데이터 줄로 오거나, 스트림이 그냥 끝납니다(`data: [DONE]` 없이). 이런 경우 중단된 것으로 처리하세요.
