본문으로 건너뛰기

연동 가이드

클라이언트는 그대로, Base URL과 model 값만 바꾸세요.

여기의 텍스트 모델은 여러분의 SDK가 이미 쓰는 프로토콜을 씁니다. Chat Completions, 무상태 Responses 서브셋, Anthropic Messages, Google generateContent. 흥미로운 지점은 대상 모델이 선언하지 않은 매개변수가 어떻게 되느냐입니다.

해결 과제

호환 레이어는 보통 말하지 않음으로써 속입니다

전형적인 실패는 500이 아닙니다. 게이트웨이가 받아들이고, 버리고, 아무 말도 하지 않은 매개변수입니다. 그래서 모델은 여러분의 temperature도, 도구 정의도, 응답 형식도 없이 돌았고, 결과는 망가진 게 아니라 그냥 아쉬워 보입니다.

01

선언되지 않은 매개변수는 버려지지 않고 거부됩니다

messages, tools, tool_choice, response_format, max_tokens, temperature, top_p는 모델이 선언한 같은 이름의 필드로 매핑됩니다. 그 밖의 것은 모델 스키마로 전달되고, 모델이 선언하지 않았다면 400입니다. 침묵은 답이 될 수 없습니다.

02

오류 형태는 호출한 프로토콜을 따릅니다

/v1에서는 본문이 OpenAI나 Anthropic 오류 객체이고, /api/v1이 쓰는 {code, msg, data, request_id} 봉투가 아닙니다. 두 면을 섞어 쓴다면 둘 다 처리하세요.

03

스트리밍과 정산은 별개입니다

stream: true는 data: [DONE]으로 끝나는 chat.completion.chunk 이벤트를 돌려줍니다. 과금은 여전히 실측 사용량을 따르므로 중간에 끊은 스트림도 공짜가 아닙니다.

구현 방식

엔드포인트를 바꾸고 평가를 다시 돌리세요

base_url과 api_key를 바꾸고 model 문자열을 GET /v1/models의 값으로 교체한 뒤, 이미 있는 테스트를 돌리세요. 어떤 매개변수에서 400이 온다면 그 모델은 애초에 그것을 지원한 적이 없다는 뜻이고, 조용히 버리는 구현에서는 얻을 수 없던 정보입니다.

OpenAI 호환 클라이언트라면 무엇이든 됩니다. 바뀌는 것은 Base URL과 model 값뿐입니다.

POST /v1/chat/completions

from openai import OpenAI

client = OpenAI(
    base_url="https://api.spicyapi.ai/v1",
    api_key=os.environ["SPICY_API_KEY"],
)

stream = client.chat.completions.create(
    model="<publisher>/<model>/chat",          # exact value from GET /v1/models
    messages=[{"role": "user", "content": "Summarise these notes in three bullets."}],
    temperature=0.7,
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

text/event-stream

data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"- "}}]}
data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"Ships"}}]}
data: [DONE]

계약

먼저 못 박아 둘 항목

OpenAI 호환 LLM API: Base URL만 바꾸세요 — 먼저 못 박아 둘 항목
필드 또는 헤더값 또는 상한
POST /v1/chat/completionschat.completion · SSE with stream: true
GET /v1/modelsevery callable model value
Authorization: Bearer · x-api-key · x-goog-api-keyaccepted on /v1
undeclared parameter400 · never silently dropped

좌우로 밀어 모든 항목을 확인하세요.

연동

첫 호출에서 운영까지

  1. 01키를 만들고 GET /v1/models로 지금 호출 가능한 식별자를 가져옵니다.
  2. 02클라이언트를 Base URL로 향하게 하고 먼저 비스트리밍으로 한 번 보냅니다. 표준 chat.completion 객체가 돌아옵니다.
  3. 03스트리밍을 켜고 읽기 쪽이 chat.completion.chunk와 [DONE]을 처리하는지 확인합니다.
  4. 04콘솔에서 키별 사용량을 보며, 운영 트래픽을 보내기 전에 일일 상한을 설정합니다.

적합성

이 경로가 맞는 경우

이럴 때 고르세요

  • 이미 동작하는 OpenAI·Anthropic·Google 클라이언트 코드가 있고 뒤의 모델만 바꾸고 싶다.
  • 이미지·영상·텍스트를 하나의 키, 하나의 잔액, 하나의 소비 상한으로 묶고 싶다.

이럴 때는 다른 길로

  • 서버 측 상태를 가진 스레드나 어시스턴트에 의존하는 경우. 여기서 지원하는 것은 무상태 Responses 서브셋입니다.
  • 미디어 출력이 필요한 경우. 그건 createTask, 또는 이미 그 형태를 쓰는 클라이언트를 위한 Videos 투영으로 갑니다.

근거

직접 확인할 수 있는 것

네 개의 프로토콜 면, 하나의 키

/v1/chat/completions, /v1/responses, /v1/messages, /v1beta/models/{model}:generateContent가 모두 같은 키로 인증합니다. Authorization: Bearer, x-api-key, x-goog-api-key는 각 SDK가 기대하는 자리에서 받아들여집니다.

모델 목록이 곧 계약입니다

GET /v1/models는 모든 /v1과 /api/v1 동작이 받아들이는 식별자를 그대로 돌려주고 제작사는 owned_by에 들어갑니다. 가격은 계정별이라 비공개인 /api/v1/models에 있습니다.

검증·제한·보류는 공유됩니다

호환 레이어는 네이티브 면과 같은 인증, 레이트 리밋, 입력 검증, 가격 계산, 자금 보류를 씁니다. 다른 것은 봉투뿐입니다.

출시 전

확인해 둘 플랫폼 동작

  • 키는 서버에 두세요. URL 쿼리 문자열에 담긴 자격 증명은 절대 받지 않습니다.
  • 문의에 대비해 호출마다 프로토콜 자체의 응답 id를 기록하세요.
  • 지원하지 않는 매개변수의 400을 사용자에게 어떻게 보여줄지 출시 전에 정하세요.
  • 잔액에만 기대지 말고 키별 일일·월간·누적 상한을 설정하세요.

자주 묻는 질문

이 페이지에서 자주 나오는 질문

Base URL과 model 문자열을 설정할 수 있는 클라이언트라면 무엇이든 됩니다. OpenAI 형태는 /v1/chat/completions와 /v1/responses, Anthropic은 /v1/messages, Google GenAI는 generateContent 경로를 씁니다.

모델

이 작업에 바로 호출할 수 있는 모델

각 링크는 해당 모델 계열 페이지로 이동합니다. 입력, 상한, 콘텐츠 방침, 단위당 현재 가격을 그곳에서 확인할 수 있습니다.

다음

텍스트 모델로 클라이언트를 돌리기

기존 OpenAI·Anthropic·Google 클라이언트를 그대로 가리키세요. 무엇이 그대로 통하고, 무엇이 일부러 거부되며, 텍스트는 어떻게 과금되는지.

관련 가이드