본문으로 건너뛰기
KeuralDocs
개발자

Keural API

API 키로 OpenAI Chat Completions 형식의 요청을 보냅니다.

Keural에 등록된 모델을 OpenAI Chat Completions 형식으로 호출합니다.

Base URL은 https://<환경별 공개 API 도메인>/llm/v1 형식입니다. 공개 API 도메인은 환경마다 다르므로 관리자에게 확인합니다.

메서드경로설명
POST/llm/v1/chat/completions대화 생성 (스트리밍 지원)
GET/llm/v1/models키에 연결된 모델 목록
GET/llm/v1/models/{model}키에 연결된 모델 정보

임베딩, 이미지 생성, 음성, Responses API 경로는 지원하지 않으며 404를 반환합니다.

이용 흐름

단계하는 일
1. 키 발급설정 → API에서 모델을 고르고 키를 받습니다. 모델 ID와 키를 복사해 둡니다.
2. 클라이언트 연결앱이나 코드에 Base URL, API 키, 모델 ID를 입력합니다.
3. 이용과 관리같은 화면에서 사용량을 확인하고, 키를 재발급하거나 회수합니다.

준비 사항

항목내용
Keural 계정로그인 가능한 계정
API 메뉴설정에 API 메뉴가 없으면 관리자에게 기능 활성화를 요청합니다.
조직 멤버 권한조직 워크스페이스에서 키를 받으려면 조직 관리자가 내 API 사용을 허용해야 합니다. 조직 멤버의 API 권한 참고
Base URL관리자가 안내한 공개 API 주소
클라이언트OpenAI API 호환 연결을 지원하는 앱이나 SDK

API 키 발급

  1. 계정 메뉴에서 설정 → API를 엽니다. 데스크톱 앱과 모바일 앱에서는 도구 구역에 있습니다.
  2. API 키 탭에서 키 소속(개인 워크스페이스 또는 조직 워크스페이스)과 Model ID를 고릅니다.
  3. 필요하면 새 키 만료일을 정합니다. 비워 두면 회수할 때까지 무기한입니다.
  4. 키 발급을 누르고 키 복사로 키를 복사해 보관합니다. 키 원문은 이때 한 번만 표시됩니다.
  • 키는 고른 워크스페이스와 모델 하나에 연결됩니다. 사용량은 키를 발급한 사람에게 귀속됩니다.
  • 같은 워크스페이스·모델에는 키가 하나만 있습니다. 새 키가 필요하면 기존 키를 재발급하거나 회수합니다.
  • 키를 잃어버리면 재발급합니다. 재발급하면 이전 키는 즉시 무효가 됩니다.
  • 발급할 수 있는 모델이 없으면 모델 공개 설정, 요금제, 조직 API 권한을 관리자에게 확인합니다.

조직 멤버의 API 권한

조직 소유자·관리자용입니다. 조직 워크스페이스에서 멤버가 키를 받으려면 관리자가 먼저 허용해야 합니다. 모든 멤버의 기본값은 차단입니다.

조직 관리 → 조직 API 관리는 다음 세 구역으로 구성됩니다. 메뉴가 없으면 API 기능이 꺼져 있거나 조직 관리 권한이 없는 계정입니다.

구역하는 일
사용자별 API 권한멤버마다 API 사용 허용을 켜고 끕니다.
발급된 키조직에서 발급된 키의 상태를 보고 회수합니다. 키 원문은 볼 수 없습니다.
API 사용량조직에서 발급된 키의 요청과 토큰 사용량을 봅니다.
동작결과
허용 켜기그 멤버가 조직 워크스페이스에서 키를 발급할 수 있습니다.
허용 끄기새 발급과 기존 키의 호출이 막힙니다. 발급된 키는 자동으로 삭제되지 않으므로 필요하면 발급된 키에서 회수합니다.

멤버가 조직을 나가거나 제거되면 그 멤버가 조직에서 받은 키는 자동으로 회수됩니다.

클라이언트에 연결

OpenAI API 호환 앱(챗 클라이언트, IDE 확장, 자동화 도구 등)에 다음 세 값을 입력합니다.

값입력할 내용앱별 항목 이름
Base URL관리자가 안내한 공개 API 주소(…/llm/v1)Base URL, API Base, Endpoint, Host
API Key발급받은 키(앞뒤 공백 없이)API Key, Token, Secret Key, Authorization
Model발급 화면의 Model ID. 키에 연결된 모델과 정확히 같아야 합니다Model, Model ID, Model Name
  1. 앱 설정에서 OpenAI 호환 연결(Connection)을 추가합니다.
  2. Base URL과 API Key를 입력하고 저장합니다.
  3. 모델 목록에서 모델을 고릅니다. 목록에는 키에 연결된 모델 하나만 표시됩니다.
  4. 짧은 메시지를 보내 응답을 확인합니다.

요청 형식은 다음과 같습니다.

구분내용
대화 요청POST <Base URL>/chat/completions
모델 조회GET <Base URL>/models
인증 헤더Authorization: Bearer <발급받은 키>
콘텐츠 헤더Content-Type: application/json

첫 요청

export KEURAL_API_KEY='발급받은_키'
export KEURAL_BASE_URL='https://<환경별 공개 API 도메인>/llm/v1'
export MODEL_ID='발급 화면의 모델 ID'

curl "$KEURAL_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $KEURAL_API_KEY" \
  -H 'Content-Type: application/json' \
  -d "{\"model\":\"$MODEL_ID\",\"messages\":[{\"role\":\"user\",\"content\":\"안녕하세요.\"}]}"

요청 본문의 model은 키에 연결된 모델 ID와 같아야 합니다. provider/모델ID처럼 앞에 경로가 붙으면 마지막 / 뒤를 비교합니다. 다르면 403을 반환합니다. 응답의 model에는 항상 키의 모델 ID가 담깁니다.

from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["KEURAL_API_KEY"],
    base_url=os.environ["KEURAL_BASE_URL"],
)
res = client.chat.completions.create(
    model=os.environ["MODEL_ID"],
    messages=[{"role": "user", "content": "안녕하세요."}],
)
print(res.choices[0].message.content)

지원하는 요청 필드

최상위 필드는 아래 18개만 받습니다. 다른 필드를 보내면 400을 반환합니다. 값이 null인 선택 필드는 보내지 않은 것으로 처리합니다.

필드규칙
model필수. 키의 모델 ID
messages필수. 1~4,096개
stream · stream_optionsstream_options는 stream: true일 때만 보냅니다. include_usage를 지원합니다.
tools최대 128개. 함수 이름은 [A-Za-z0-9_-] 1~64자
tool_choicenone · auto · required · 특정 함수. required는 tools가 있어야 합니다.
parallel_tool_calls모델이 지원하지 않으면 400
response_formattext · json_object · json_schema
max_tokens · max_completion_tokens둘 중 하나만 보냅니다. 보내지 않으면 4,096(모델 상한이 더 낮으면 그 값). 모델 상한을 넘으면 400
temperature0~2. 모델이 지원하지 않으면 400
top_p0~1
frequency_penalty · presence_penalty-2~2
stop문자열 또는 최대 4개 배열
seed정수
user최대 256자
n1만

메시지

역할받는 필드
system · developercontent, name
usercontent(문자열 또는 텍스트·이미지 파트 배열), name
assistantcontent, name, refusal, tool_calls
toolcontent, tool_call_id
  • tool 메시지는 앞선 tool_calls의 id에 한 번씩만 답합니다.
  • 이미지 파트(image_url)는 이미지를 받는 모델의 user 메시지에만 넣습니다. http·https 주소나 PNG·JPEG·GIF·WebP의 base64 data URI를 넣고, detail은 auto · low · high입니다.

본문

항목한도
Content-Typeapplication/json
크기1MiB
JSON 구조최상위 객체 하나, 중첩 깊이 64 이하, 같은 키 중복 금지
요청 시간최대 600초

본문 규칙을 어기면 400이고 param은 body입니다.

스트리밍

요청에 "stream": true를 넣으면 SSE로 응답합니다. 청크는 data: ... 이벤트로 전송되고, 마지막에 data: [DONE]이 전송됩니다. "stream_options": {"include_usage": true}를 넣으면 [DONE] 직전에 토큰 사용량 청크가 추가로 전송됩니다.

include_usage를 넣으면 모든 청크에 usage: null이 담기고, 마지막 사용량 청크는 choices가 빈 배열입니다. 비스트리밍 응답은 입력·출력 토큰이 모두 확인됐을 때만 usage를 담습니다.

응답 id는 chatcmpl-<x-request-id> 형식입니다. 모든 응답 헤더에는 x-request-id가 붙습니다.

스트리밍 중 오류가 나면 오류 JSON을 담은 data: 이벤트가 전송되고 [DONE] 없이 연결이 끝납니다. 청크 하나가 1MiB를 넘거나 응답이 16MiB를 넘으면 503으로 끝납니다.

curl -N "$KEURAL_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $KEURAL_API_KEY" \
  -H 'Content-Type: application/json' \
  -d "{\"model\":\"$MODEL_ID\",\"messages\":[{\"role\":\"user\",\"content\":\"안녕하세요.\"}],\"stream\":true,\"stream_options\":{\"include_usage\":true}}"

사용 한도

사용자·조직·모델 단위로 동시 요청 수, 분당 요청 수(RPM), 분당 토큰 수(TPM)가 제한됩니다. 실제 값은 환경마다 다릅니다.

분당 토큰은 요청을 받을 때 미리 차감합니다. 입력은 영문 4글자당 1토큰, 그 밖의 글자는 1글자당 1토큰, 이미지 1장은 2,000토큰으로 계산합니다. 출력은 max_tokens(최대 4,096)만큼 차감하므로, 출력 상한을 필요한 만큼만 지정하면 한도 여유가 커집니다.

429 code원인Retry-After
rate_limit_exceededRPM · TPM · 동시 요청 수 초과RPM·TPM은 60초, 동시 요청은 1초
api_busy서버의 처리 용량 초과없음. 잠시 뒤 다시 시도합니다.
upstream_rate_limit모델 공급사의 한도 초과없음

키 관리

설정 → API → API 키 탭에서 키 상태(유효 · 만료 · 회수됨)를 확인하고 재발급하거나 회수합니다.

키는 krl_llm_으로 시작하는 51자 문자열입니다. 키 소속 하나에 키는 하나이며, 이미 있으면 재발급합니다. 만료일은 오늘 이후로만 정할 수 있습니다.

동작결과유의할 점
재발급새 키를 받습니다.이전 키는 즉시 무효가 됩니다. 연결한 앱의 키도 바꿉니다.
회수키를 즉시 차단합니다.키 노출이 의심될 때 씁니다. 회수한 키는 복구할 수 없습니다.

사용량 확인

API 요청과 토큰 사용량은 다음 두 곳에서 확인합니다.

위치내용
설정 → API → API 사용량 탭지금 워크스페이스에서 내가 발급한 키의 사용량
조직 관리 → 조직 API 관리 아래쪽 API 사용량조직에서 발급된 모든 키의 사용량(조직 소유자·관리자)

조회 조건

조건설명
시작 시각 · 종료 시각한국 시간 기준. 시작 시각은 포함, 종료 시각은 미포함입니다. 비워 두면 최근 7일이며, 한 번에 최대 90일까지 조회합니다.
Model ID특정 모델의 요청만 조회합니다. 비워 두면 전체입니다.
요청 상태전체 · 진행 중 · 완료 · 실패 · 중단 · 미확정 중에서 고릅니다.

조건을 정하고 조회를 누릅니다. 최근 요청을 반영하려면 새로고침을 누릅니다.

화면에 나오는 값

  • 적용 조회 기간: 실제로 조회된 기간입니다. 시작·종료 시각을 비웠거나 90일을 넘기면 조정된 기간이 표시됩니다.
  • 요청 수와 입력 토큰 · 출력 토큰 · 전체 토큰 합계: 확인된 값만 합산합니다. 확인되지 않은 토큰은 미확인으로 표시합니다.
  • 요청 목록: 요청마다 요청 시각, Model ID, 요청 상태, 입력·출력·전체 토큰을 표시합니다. 한 쪽에 20개씩 표시되며 이전 · 다음으로 넘깁니다.

행의 요청 세부 정보를 누르면 다음 값이 표시됩니다.

항목설명
요청 ID문의할 때 전달하는 값
응답 방식스트리밍 또는 일반 응답
사용량 확인 상태확인됨 · 일부 확인 · 미확인
종료 시각 · 응답 시간(ms)요청이 끝난 시각과 걸린 시간
캐시 읽기 · 캐시 생성 · 추론 토큰모델이 이 값을 반환한 경우에만 표시

스트리밍 요청은 stream_options.include_usage 없이도 사용량이 기록됩니다. 요청이 중간에 끊기면 일부 확인이나 미확인으로 남을 수 있습니다.

오류 형식

오류는 OpenAI 호환 형식으로 반환합니다.

{
  "error": {
    "message": "사람이 읽을 수 있는 오류 설명",
    "type": "authentication_error",
    "code": "invalid_api_key",
    "param": null
  }
}

type은 상태 코드로 정해지고, code로 원인을 구분합니다.

상태typecode원인
400invalid_request_errorinvalid_request필드·값·본문 규칙 위반. param에 문제가 된 필드
400invalid_request_errorupstream_rejected_request모델 공급사가 요청을 거부
401authentication_errorinvalid_api_key키 형식 오류, 키 없음, 만료·회수·재발급, Authorization 헤더가 둘 이상
403permission_errorapi_disabledKeural API 기능이 꺼져 있음
403permission_errormodel_api_disabled모델의 API 공개가 꺼져 있음
403permission_errormodel_not_allowedmodel이 키의 모델과 다름, 멤버 API 권한 없음
404invalid_request_errornot_found없는 경로
405invalid_request_errormethod_not_allowed잘못된 메서드. Allow 헤더에 허용 메서드
429rate_limit_error위 사용 한도 표한도 초과
503server_errorupstream_timeout600초 안에 응답이 끝나지 않음
503server_errorinvalid_upstream_response공급사 응답 형식 이상, 스트림 크기 초과
503server_errordependency_unavailable · unsupported_provider일시적인 내부 문제. x-request-id를 담아 문의

문제 해결

증상응답 코드확인할 항목
모델 목록이 비어 있거나 연결에 실패합니다404 · 405Base URL이 …/llm/v1로 끝나는지
인증에 실패합니다401키 오타·앞뒤 공백, 만료·회수·재발급 여부
연결은 되는데 모델을 쓸 수 없습니다403모델 ID가 키의 모델과 같은지, 조직 API 권한
응답이 늦거나 가끔 실패합니다429사용 한도
잠시 응답이 오지 않습니다5xx잠시 뒤 다시 시도
사용량이 보이지 않거나 실제와 다릅니다—조회 기간과 키 소속 워크스페이스

해결되지 않으면 다음 정보를 담아 관리자에게 문의합니다. 키 원문과 프롬프트 내용은 보내지 않습니다.

  • 발생 시각
  • 사용한 모델 ID
  • 클라이언트 앱의 이름과 버전
  • 응답 헤더의 x-request-id
  • 화면에 나온 오류 메시지

이 페이지의 내용