# API 변경 기록 > 응답 머리글 · 칸 · 상태 코드 · 오류 갈래가 바뀐 날과 고칠 코드를 최근 순으로 적어요. > 원문: https://oneport.kr/docs/changelog 손님 코드가 읽는 동작이 바뀐 날만 적어요. 새 모델 · 끝나는 모델은 https://oneport.kr/changes 예요. 코드에선 끝나는 날을 GET /v1/models 줄의 retirement(date · successors)로 읽어요 — https://oneport.kr/changes 는 사람이 보는 페이지예요. 끝난 이름을 부르면 404 model_not_found 예요(2026-10-23 에 o1 · o1-pro · o3-mini · o4-mini · gpt-4.1-nano · gpt-image-1 판매가 끝났어요). 이 기록은 2026-10-26 부터예요. 그 전에 바뀐 동작은 여기 없어요 — 지금 동작은 「에러」 장(https://oneport.kr/docs/errors.md)이 기준이에요. 다만 바로 전 주(2026-10-25)에 바뀐 머리글은 이래요 — 429 key_limit_exceeded · group_limit_exceeded 에 x-should-retry: false 가 붙고(2026-10-30 부터 key_limit_exceeded 중 error.reason held_by_others 만 x-should-retry: true · Retry-After: 5 예요 — 그날 줄), effort 를 못 받는 모델에서 빼고 보낸 reasoning_effort 가 x-gateway-ignored-params 에 적혀요. 모델 회사로 보낸 글 문 응답의 x-gateway-fallback-depth(2026-08-25 부터) · x-gateway-source(2026-09-23 부터)는 이 기록 전부터 와요 — x-gateway-source 는 저희 기록용이라 코드에서 가르지 마세요. 날짜는 그 동작이 들어간 날(한국 시간)이에요. 고칠 코드에 SDK 이름이 없으면 openai SDK · Anthropic SDK 가 같은 코드예요 — 다만 줄 끝 주석에 requests · fetch 가 적힌 코드(GET /v1/requests/{id} · /v1/credits · /v1/key · /v1/keys · /v1/connectors · /v1/videos · /v1/tasks 등)는 SDK 가 아니라 그렇게 받은 응답을 읽는 코드예요. Node 줄의 err.headers?.get(…) 은 err.headers 가 Headers 객체인 판(openai SDK v5 이상) 기준이에요 — 일반 객체로 주는 판(openai SDK v4)은 err.headers?.["retry-after"] 처럼 읽어요(v4 에서 .get 을 부르면 TypeError). 줄마다 머리만 실었어요 — 줄 본문 · 고칠 코드와 그 전 날짜는 전체 판 https://oneport.kr/docs/changelog.full.md 에 있어요. ## 2026-11-03 - **[바뀜] 채팅 문으로 Gemini 서버 도구(검색 · URL 읽기 · 코드 실행)를 실으면 400** — POST /v1/chat/completions ## 2026-11-02 - **[바뀜] 초·중·고 학교 지갑의 새 키 — audience 를 안 보내면 선생님 키** — POST /v1/keys - **[새 기능] 한도 429 에 error.resets_at — 다시 열리는 시각** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/embeddings · /v1/images/* · /v1/audio/* · POST /v1/videos · POST /v1/tasks - **[바뀜] 글 문 스트림 상한이 약 4분 30초에서 약 12분 50초로** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[바뀜] 커넥터 부탁 reason 은 그 부탁을 만든 키에만** — POST /v1/connectors/requests · GET /v1/connectors/requests/{id} - **[고침] 브라우저에서 /v1 을 빠뜨린 글 문 주소 — 안내 404 가 CORS 오류 대신 읽혀요** — POST /chat/completions · /messages · /responses · GET /models(키를 실은 것) — /v1 이 빠진 주소 ## 2026-11-01 - **[새 기능] GET /v1/key 의 group 에 반 기간(starts_on · ends_on)과 closed_reason** — GET /v1/key - **[바뀜] /mcp — 🏫 학교장터 표시 · s2b_only 는 옵션 단위 · 물품번호 줄은 등록을 마친 번호만** — POST https://schoolorder.kr/mcp - **[바뀜] /v1/keys — expires_on 에 빈 글을 보내면 400** — POST /v1/keys · PATCH /v1/keys/{id} - **[바뀜] 조회 문과 /v1/keys 의 일시 실패 503 api_error 에 Retry-After: 2** — GET /v1/credits · GET /v1/key · GET /v1/models · /v1/keys · /v1/keys/{id} - **[바뀜] /v1/chat/completions — n 이 2 이상이면 미리 잡는 출력 몫이 n 배 · n 은 1–128 정수만** — POST /v1/chat/completions(Claude 밖 모델) - **[바뀜] 주소(URL)로 붙인 그림 · 문서도 미리 잡는 몫에 들어가요** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[바뀜] /mcp — 준비중 · 일시중지 상품은 값을 안 내요 · 견적 수량은 999 까지 · 주문이 안 서는 견적엔 까닭 한 줄 · 상품을 못 읽으면 isError** — POST https://schoolorder.kr/mcp · 오피스오더 /mcp - **[바뀜] GPT-5.6 이후 모델은 미리 잡는 입력 몫을 캐시 쓰기 단가로** — POST /v1/chat/completions · /v1/responses - **[바뀜] 파일을 id 로 부르는 칸(file_id)은 400** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[바뀜] 스페이스 지갑이 멈춘 키의 401 account_inactive 는 스페이스 관리자에게** — /v1 의 모든 문(키를 실은 요청) - **[바뀜] GET /v1/videos/{id}/content — 한 번에 기다리는 시간 30초 → 2분** — GET /v1/videos/{id}/content - **[바뀜] /docs.md · /docs/<장>.md 는 핵심 판, 전체 판은 .full.md** — GET https://oneport.kr/docs.md · /docs/<장>.md · /docs/<장>.full.md - **[고침] GET /v1/models — 단가표를 못 읽으면 빈 목록이 아니라 503 api_error** — GET /v1/models · GET /v1/models/{id} - **[고침] 시작 기록을 못 적은 503(Idempotency-Key 요청) — code api_error · error.reason dispatch_unavailable · Retry-After: 2** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] 꺼진 키 401 문장이 대시보드 버튼 이름 「폐기」를 말해요** — API 키를 받는 /v1 문 전부 - **[고침] 402 · 429 문장이 따를 수 있는 출구만 말해요 — 출력 상한 없는 /v1/responses · 주소 문서** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] DELETE /v1/videos/{id} — 파일을 못 지우면 200 이 아니라 503 api_error** — DELETE /v1/videos/{id} - **[고침] /v1/keys/{id} — 키 id 모양(uuid)이 아니면 503 이 아니라 404** — GET · PATCH · DELETE /v1/keys/{id} - **[고침] 읽기를 멈춘 스트림도 그때까지 쓴 몫을 정산해요** — POST /v1/chat/completions · /v1/messages · /v1/responses ## 2026-10-31 - **[고침] GET /v1/models/{id} — / 가 든 id 를 인코딩 없이 불러도 돼요** — GET /v1/models/{id} - **[고침] /v1 문의 지원 안 하는 메서드는 JSON 405 method_not_allowed** — /v1 의 문 대부분(HEAD · OPTIONS · /v1/keys 빼고 · 작업 문은 같은 날 따로) - **[고침] 두 머리글에 다른 값을 같이 보내면 어떤 401 이든 어느 머리글을 읽었는지 알려 줘요** — /v1 의 모든 문 — POST /v1/chat/completions · /v1/messages · /v1/responses 등(관리 키 문 /v1/keys 빼고) - **[고침] 판매가 끝난 모델의 날짜 붙은 이름도 404 가 끝난 날 · 바꿔 넣을 모델을 알려 줘요** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/messages/count_tokens · /v1/images/generations · /v1/images/edits - **[고침] 관리 키를 잠깐 못 읽으면 401 이 아니라 503 api_error** — GET · POST /v1/keys · GET · PATCH · DELETE /v1/keys/{id} - **[바뀜] /mcp — JSON-RPC 묶음은 20개까지 · id 없는 tools/call 은 실행하지 않아요** — POST https://schoolorder.kr/mcp · 오피스오더 /mcp - **[고침] 작업 결과 파일 — 4.5MB 넘는 파일도 받아요** — GET /v1/tasks/{id}/files/{fileId} - **[고침] GET /v1/videos — 목록을 못 읽으면 빈 목록이 아니라 503 api_error** — GET /v1/videos - **[고침] 영상 받기 — 보관 7일(expires_at)이 지나면 정리 전이어도 404** — GET /v1/videos/{id}/content - **[고침] 읽어주기 — 손님이 읽기를 멈춰도 기한(약 4분 30초)에 저희가 끊고 0** — POST /v1/audio/speech - **[고침] 오피스오더에서 시작한 커넥터 계정 잇기가 끝까지 돼요** — GET /v1/connectors 의 link_url(오피스오더) - **[고침] 나노바나나 — 21:9 size(예: 2520x1080)를 받아요** — POST /v1/images/generations · /v1/images/edits(gemini-…-image) - **[바뀜] Responses — 12시간 캐시("12h")는 400 invalid_request_error · error.param** — POST /v1/responses - **[바뀜] gemini-3.1-flash-lite — 채팅 문에 오디오 조각을 보내면 400** — POST /v1/chat/completions - **[바뀜] 끊긴 Claude 흐름 — 누적 출력 수를 못 받았으면 흘려보낸 글로 출력을 어림해요** — POST /v1/chat/completions · /v1/messages(Claude · stream: true) - **[바뀜] 검열 · 작업 문 — 스페이스 키에도 전송 정책(space_content_policy)** — POST /v1/moderations · POST /v1/tasks - **[바뀜] 그림 문 — 미리 잡는 몫에 prompt 글 몫 · 차감은 잡은 몫까지** — POST /v1/images/generations · /v1/images/edits - **[고침] 그림 · 소리 · 검열 문 — 저희 쪽 사정으로 모델 회사가 받지 않으면 503 api_error provider_unavailable** — POST /v1/images/generations · /v1/images/edits · /v1/audio/speech · /v1/audio/transcriptions · /v1/moderations - **[고침] Grok 영상 — 접수 응답을 잃어도 503 이 아니라 200 queued 작업** — POST /v1/videos - **[새 기능] GET /v1/models 의 scheduled_change 에 상위 구간(tier) 예고** — GET /v1/models · GET /v1/models/{id} - **[바뀜] 임베딩 400 — 모델 회사가 input 이 아닌 칸을 거절하면 error.reason vendor_param_rejected · error.param** — POST /v1/embeddings - **[고침] 모델 목록을 잠깐 못 읽으면 404 가 아니라 503 api_error** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/messages/count_tokens · /v1/moderations · /v1/embeddings · /v1/images/generations · /v1/images/edits · /v1/audio/speech · /v1/audio/transcriptions · /v1/videos - **[고침] 글 문 — 입력 어림이 모델 창보다 크면 미리 잡는 몫을 창 크기로 줄여요** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[새 기능] 401 error.reason unset_key — 키 자리에 null · undefined · None** — /v1 의 모든 문(관리 키 문 /v1/keys 빼고) - **[새 기능] 429 error.reason hold_exceeds_key_limit — 학생 키에서 요청 하나가 월 한도보다 클 때** — POST /v1/chat/completions · /v1/messages · /v1/responses 등 키 한도를 재는 문 - **[새 기능] 임베딩 403 space_content_policy 에 error.reason token_input** — POST /v1/embeddings (전송 정책을 켠 스페이스 키) - **[바뀜] 작업 — 503 session_failed 로 거절된 id 의 GET 이 POST 와 같은 rejected** — GET /v1/tasks/{id} - **[새 기능] 작업 400 에 error.param — 고칠 칸 이름** — POST /v1/tasks - **[고침] 작업 문의 지원 안 하는 메서드는 JSON 405 method_not_allowed** — GET · PUT · PATCH · DELETE /v1/tasks · POST · PUT · PATCH /v1/tasks/{id} - **[바뀜] 날짜 붙은 같은 종류 모델 이름은 404 model_not_found — 임베딩 · 읽어주기 · 받아쓰기 · 영상 · 검열** — POST /v1/embeddings · /v1/audio/speech · /v1/audio/transcriptions · /v1/videos · /v1/moderations - **[고침] Claude 로 가는 채팅의 그림 cache_control 을 옮기고 · image_url.detail 은 머리글에 · PDF 이름은 문서 제목으로** — POST /v1/chat/completions (Claude 모델) - **[고침] MCP 서버 JSON 응답에 charset=utf-8** — POST /mcp - **[바뀜] 받아쓰기 space_content_policy 의 error.code 에 이유** — POST /v1/audio/transcriptions - **[바뀜] 토큰 세기 문 — 크레딧을 산 적 없는 지갑의 키는 403 model_not_in_plan** — POST /v1/messages/count_tokens - **[새 기능] 관리 키 문 401 에도 error.reason — missing_key · malformed_key** — GET · POST /v1/keys · GET · PATCH · DELETE /v1/keys/{id} - **[고침] 접수 전 · 상태 조회 503 에 Retry-After: 2 — Idempotency-Key 를 실은 요청** — POST /v1/chat/completions · /v1/messages · /v1/responses (Idempotency-Key 를 실었을 때) · GET /v1/requests/{id} ## 2026-10-30 - **[새 기능] 커넥터 문 넷 — GET /v1/connectors · 부탁 문 셋** — GET /v1/connectors · POST /v1/connectors/requests · GET /v1/connectors/requests · GET /v1/connectors/requests/{id} - **[새 기능] 임베딩 400 에 error.reason vendor_rejected — 모델 회사가 받지 않은 요청** — POST /v1/embeddings - **[새 기능] GET /v1/key 의 month.held_credits — 아직 끝나지 않은 호출 몫** — GET /v1/key - **[새 기능] 401 에 error.reason — 키가 안 열린 까닭** — /v1 의 모든 문 — POST /v1/chat/completions · /v1/messages · /v1/responses 등(관리 키 문 /v1/keys 빼고) - **[새 기능] 실패 응답에 Location · error.status_url — Idempotency-Key 를 실은 글 문** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[새 기능] GET /v1/models 의 scheduled_change 에 차감 단가 예고** — GET /v1/models · GET /v1/models/{id} - **[바뀜] 확인이 끝난 서비스를 다시 부탁하면 approved 줄로** — POST /v1/connectors/requests · GET /v1/connectors - **[바뀜] 커넥터 목록의 link_url — 도구 칸 하나라도 needs_link 면** — GET /v1/connectors - **[바뀜] 커넥터 부탁 문 403 에 connector_request_id** — POST /v1/connectors/requests - **[바뀜] 커넥터 부탁 문 · 작업 문의 409 에 x-should-retry: false** — POST /v1/connectors/requests · POST /v1/tasks - **[바뀜] 영상 접수 때 저희 쪽 사정은 503 provider_unavailable** — POST /v1/videos - **[바뀜] 영상 error.message · 큰 Claude 모델 402 문장이 바뀌었어요** — POST /v1/videos · GET /v1/videos · GET /v1/videos/{id} · POST /v1/chat/completions · /v1/messages - **[바뀜] 키 월 한도가 아직 끝나지 않은 호출 몫까지 세요** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/embeddings · /v1/images/* · /v1/audio/* · POST /v1/videos · POST /v1/tasks - **[바뀜] 키 월 한도 429 에 error.reason held_by_others — 아직 끝나지 않은 호출 몫** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/embeddings · /v1/images/* · /v1/audio/* · POST /v1/videos · POST /v1/tasks - **[바뀜] GET /v1/models — 키 머리글을 실었는데 못 읽으면 401** — GET /v1/models · GET /v1/models/{id} - **[바뀜] 키 실은 GET /v1/models — 월 한도로 한 장도 못 만드는 그림 모델은 빠져요** — GET /v1/models · GET /v1/models/{id} - **[바뀜] 저장된 응답 · 대화를 id 로 부르는 칸은 400** — POST /v1/responses · /v1/messages - **[바뀜] Responses 의 file_search 도구는 400** — POST /v1/responses - **[고침] 키를 잠깐 못 읽은 503 — 키 실은 요청 · 상태 조회도 기다렸다 다시 보내는 신호로** — POST /v1/chat/completions · /v1/messages · /v1/responses · GET /v1/requests/{id} - **[고침] 작업 문 held 응답에 Location 없음 · 시작 못 한 작업은 같은 키로 다시** — POST /v1/tasks - **[고침] 다른 호출이 잡아 둔 몫 402 — 글 문도 한 줄 문장으로** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] 임베딩 429 rate_limit_error 에 Retry-After** — POST /v1/embeddings - **[고침] 상품 조회 MCP 서버(/mcp)를 브라우저 페이지에서 부르면 CORS 머리글** — POST /mcp · OPTIONS /mcp(스쿨오더 · 오피스오더 상품 조회 서버) - **[고침] 영상 접수 때 안전 기준 거절은 moderation_blocked 로** — POST /v1/videos - **[고침] 영상 조회 · 받기를 못 읽으면 404 대신 503** — GET /v1/videos/{id} · GET /v1/videos/{id}/content · POST /v1/videos - **[고침] 영상 내용 거절은 접수 때든 만드는 중이든 moderation_blocked** — POST /v1/videos · GET /v1/videos/{id} - **[고침] 지갑 거절 뒤 다시 부탁한 줄엔 옛 거절을 싣지 않아요** — POST /v1/connectors/requests · GET /v1/connectors/requests · GET /v1/connectors/requests/{id} - **[고침] 영상 접수 거절을 저희가 못 적었을 때 — 그 자리에서 다시 적고, 두 번 잇달아 못 적으면 503** — POST /v1/videos ## 2026-10-29 - **[새 기능] GET /v1/credits · /v1/key · /v1/keys 에 wallet_id** — GET /v1/credits · GET /v1/key · GET /v1/keys(목록) - **[새 기능] 토큰 세기 문 429 rate_limit_error 에 Retry-After** — POST /v1/messages/count_tokens - **[새 기능] 429 group_limit_exceeded 에 error.reason** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/embeddings · /v1/images/* · /v1/audio/* · POST /v1/videos · POST /v1/tasks - **[바뀜] 스페이스 전송 정책 content_limit 거절 문장 — 「나눠서 보내 주세요」** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/messages/count_tokens · /v1/embeddings - **[바뀜] 요청 상태 조회의 정산 금액 — settlement.chargedNano 대신 settlement.cost_credits** — GET /v1/requests/{id} - **[바뀜] 임베딩에서 저희 쪽 사정으로 못 보낸 요청은 503 provider_unavailable** — POST /v1/embeddings - **[바뀜] 접수하는 사이 꺼진 API 키는 401 authentication_error** — POST /v1/chat/completions · /v1/messages · /v1/responses (Idempotency-Key 를 실었을 때) - **[바뀜] 「새로 받기」로 바꾼 키도 접수 · 조회가 이어져요** — POST /v1/chat/completions · /v1/messages · /v1/responses · GET /v1/requests/{id} (Idempotency-Key 를 실었을 때) - **[고침] 「새로 받기」 순간 처리 중이던 Idempotency-Key 요청도 끝이 적혀요** — POST /v1/chat/completions · /v1/messages · /v1/responses · GET /v1/requests/{id} (Idempotency-Key 를 실었을 때) - **[고침] /v1/tasks 작업도 「새로 받기」를 따라가요 · 끈 키의 열린 작업은 멈춰요** — POST /v1/tasks · GET · DELETE /v1/tasks/{id} · GET /v1/tasks/{id}/events · GET /v1/tasks/{id}/files/{fileId} - **[고침] 받아쓰기 gpt-4o 계열의 prompt 는 글 입력 단가로 셈해요** — POST /v1/audio/transcriptions · GET /v1/models - **[고침] 실행 전에 막힌 Idempotency-Key 요청은 같은 키로 다시 받아요** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] 409 request_already_exists 에도 x-gateway-status-url** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] 실행 전에 막힌 접수의 조회 — result failed · settlement not_charged** — GET /v1/requests/{id} - **[고침] 시작 기록 없는 접수 · 15분 넘게 멈춘 접수도 같은 키로 다시 받아요** — POST /v1/chat/completions · /v1/messages · /v1/responses · GET /v1/requests/{id} - **[고침] 임베딩 오류 봉투 — held_by_others · Retry-After · 정책 code · 요청 ID · 구글 usage** — POST /v1/embeddings - **[고침] 접수 기록을 못 쓴 503 request_store_unavailable 에 Retry-After: 2** — POST /v1/chat/completions · /v1/messages · /v1/responses (Idempotency-Key 를 실었을 때) - **[고침] 영상 문 402 에도 error.reason · 503 에 Retry-After: 2** — POST /v1/videos - **[고침] 읽어주기 · 받아쓰기 요청 ID 로 사용 기록을 찾아요** — POST /v1/audio/speech · POST /v1/audio/transcriptions - **[고침] GET /v1/models 의 검열 모델은 산 크레딧의 회사와 상관없이 와요** — GET /v1/models (키를 실었을 때) - **[고침] 정산 원장 · 감사 로그 CSV 의 끝 날이 자정까지 다 들어가요** — 대시보드 「정산 원장 받기 (CSV)」 · 「감사 로그 받기」(?from · ?to) - **[고침] 사용 기록의 시각은 요청을 받은 시각이에요** — 대시보드 「정산 원장 받기 (CSV)」 · 「감사 로그 받기」 - **[고침] 스페이스 전송 정책 키도 맨 위 cache_control 을 받아요** — POST /v1/messages · /v1/chat/completions - **[고침] 기한이 끝난 키의 401 문장 — 「한도 수정」 · 「키 만들기」** — API 키로 부르는 /v1 문(기한이 끝난 키) - **[고침] 422 upstream_execution_unconfirmed 문장 — Idempotency-Key 없이 보낸 요청은 조회 대신 문의** — POST /v1/chat/completions · /v1/messages · /v1/responses (Idempotency-Key 없이 보냈을 때) ## 2026-10-28 - **[새 기능] 요청 ID 가 /v1 모든 문에** — /v1 모든 문(관리 키 문 /v1/keys 빼고) · 없는 주소의 404 - **[새 기능] 호출마다 쓴 몫 usage.cost_credits** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[새 기능] 잠시 뒤 그대로 다시 보낼 실패에 Retry-After** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[새 기능] 기한을 넘긴 504 에 error.reason "timeout"** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[새 기능] Idempotency-Key 와 요청 상태 조회 GET /v1/requests/{id}** — POST /v1/chat/completions · /v1/messages · /v1/responses · GET /v1/requests/{id} - **[새 기능] Claude 과부하 529 에 Retry-After** — POST /v1/chat/completions · /v1/messages (Claude 모델) - **[새 기능] 토큰 세기 문 503 api_error 에 Retry-After: 2** — POST /v1/messages/count_tokens - **[새 기능] 402 error.reason 세 갈래** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/images/* · /v1/audio/* · /v1/embeddings - **[새 기능] 키 한도 429 에 error.reason** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/embeddings · /v1/images/* · /v1/audio/* · POST /v1/videos · POST /v1/tasks - **[새 기능] 도중에 끊긴 스트림의 마지막 오류 이벤트** — POST /v1/chat/completions · /v1/messages · /v1/responses (stream: true) - **[바뀜] 저희 쪽 사정으로 못 보낸 요청은 503 provider_unavailable** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[바뀜] 보낸 뒤 결과를 모르는 실패는 422 upstream_execution_unconfirmed** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[바뀜] claude-sonnet-5 · claude-opus-5-5 큰 예약 — 새 anthropic-version · beta 머리글이면 보통 셈** — POST /v1/chat/completions · /v1/messages (claude-sonnet-5 · claude-opus-5-5) - **[바뀜] 학생 키의 기본 월 한도** — POST /v1/keys (관리 키) - **[바뀜] anthropic-version 2026-10-21 판의 temperature · top_p · top_k** — POST /v1/messages · /v1/messages/count_tokens - **[바뀜] 키를 새로 받아도 이번 달 · 오늘 쓴 몫이 이어져요** — GET /v1/key · 대시보드 키 「새로 받기」 - **[고침] GET /v1/models/{id} 404 의 type 을 model_not_found 로** — GET /v1/models/{id} - **[고침] Claude 를 /v1/chat/completions 로 받을 때의 usage** — POST /v1/chat/completions (Claude 모델) - **[고침] 작업 문 — 다른 호출이 잡아 둔 몫 402 · 시작 전 취소** — POST /v1/tasks · GET /v1/tasks/{id} - **[고침] 그림 문의 큰 응답** — POST /v1/images/generations · /v1/images/edits - **[고침] 영상 참고 그림의 형식을 파일 머리로** — POST /v1/videos (input_reference) ## 2026-10-27 - **[새 기능] 402 error.reason held_by_others** — POST /v1/chat/completions · /v1/messages · /v1/responses · 문장은 /v1/images/* · /v1/videos · /v1/embeddings · /v1/audio/* 도 - **[새 기능] 관리 키 문의 키 자리** — POST /v1/keys · GET /v1/keys - **[새 기능] GET /v1/models 의 tier 에 상위 구간 캐시 단가** — GET /v1/models - **[바뀜] 키를 실은 GET https://oneport.kr/models 는 JSON 404** — GET https://oneport.kr/models (/v1 빠진 주소) - **[바뀜] 쓴 몫 칸은 올린 정수** — GET /v1/key · GET /v1/keys · GET /v1/credits - **[바뀜] 도구를 실은 GPT-5.6 · GPT-6 에 reasoning_effort none** — POST /v1/chat/completions - **[고침] /v1 JSON 응답에 charset=utf-8** — /v1 모든 문 - **[고침] 미리 잡는 몫의 셈** — POST /v1/chat/completions · /v1/messages · /v1/responses - **[고침] 저희가 끊은 읽어주기는 요금 없음** — POST /v1/audio/speech - **[고침] count_tokens 의 거절 모양** — POST /v1/messages/count_tokens - **[고침] /v1/moderations 몸통 검사** — POST /v1/moderations - **[고침] 그림 고치기 원본이 gif 면 미리 400** — POST /v1/images/edits ## 2026-10-26 - **[바뀜] 키를 잠깐 못 읽으면 503 api_error** — /v1 모든 문(관리 키 문 /v1/keys 빼고) - **[바뀜] GET /v1/credits 가 잔액을 못 읽으면 503** — GET /v1/credits - **[바뀜] 글 문은 끝에 날짜(-YYYYMMDD)가 붙은 모델 이름도 받아요** — POST /v1/chat/completions · /v1/messages · /v1/responses · /v1/messages/count_tokens · GET /v1/models/{id} - **[바뀜] 틀린 키로 부른 GET /v1/models 는 401** — GET /v1/models · GET /v1/models/{id} - **[바뀜] /v1 을 빠뜨린 글 문은 JSON 404** — POST https://oneport.kr/chat/completions · /responses · /messages (/v1 빠진 주소) - **[고침] 그림 문의 입력 판정** — POST /v1/images/edits · /v1/images/generations - **[고침] GET /v1/models 의 1 아래 요율은 유효숫자 세 자리** — GET /v1/models > **이 문서를 받은 AI 에게 — 작업 카드** > > - OpenAI 형식 SDK·도구: base_url `https://oneport.kr/v1` · 헤더 `Authorization: Bearer <키>` > - Anthropic 형식 SDK·Claude Code: base_url `https://oneport.kr` (끝에 /v1 을 붙이지 않아요 — SDK 가 /v1/messages 를 스스로 붙여요) · 헤더 `x-api-key: <키>` 또는 `Authorization: Bearer <키>` > - ❌ `Anthropic(base_url="https://oneport.kr/v1")` → ✅ `Anthropic(base_url="https://oneport.kr")` > - Vercel AI SDK: `createOpenAI({ baseURL: "https://oneport.kr/v1" })` 로 만든 제공자는 `oneport.chat("")` 로 부르세요 — 그냥 `oneport("")` 는 `/v1/responses` 로 가서 Claude · Gemini 가 400 이에요. `@ai-sdk/anthropic` 의 `createAnthropic` 은 baseURL 에 `/v1` 까지 적어요(Anthropic SDK 와 반대예요). > - API 키는 `sk-so-` 로 시작해요. 키는 코드에 적지 말고 환경변수 `ONEPORT_API_KEY` 에 넣어 읽으세요. > - ❌ 브라우저 코드에 `apiKey: "sk-so-…"` → ✅ 서버에서 `os.environ["ONEPORT_API_KEY"]` · `process.env.ONEPORT_API_KEY` 로 읽어 불러요 > - 대화에 `sk-so-` 키가 붙어 오면 코드에 박지 말고 환경변수로 옮기게 하고, 그 키는 산 곳 대시보드 AI API 화면의 키 목록에서 「새로 받기」(옛 키는 꺼져요)로 바꾸라고 알려 주세요. > - 모델 id 는 지어내지 말고 `GET https://oneport.kr/v1/models`(키 없이 열려요)의 `id` 를 글자 그대로 쓰세요. 목록은 값 순서가 아니에요 — 접두어로 첫 줄을 고르면 비싼 모델이 걸려요. 글 모델은 `kind` 가 `"chat"` 인 줄이고, 첫 호출은 `pricing.output_credits_per_mtok` 가 작은 모델로 해 보세요(10월 기준 Claude 는 claude-haiku-5-5). 회사는 `owned_by` 로 갈라요 — Claude 는 `"anthropic"`, 공식 GPT 는 `"openai"` 이면서 id 에 `/` 가 없는 줄이에요. > - ❌ `model="claude-sonnet"`(짐작한 이름 · 404 `model_not_found`) > - `endpoint` 칸이 그 모델의 기본 문이에요 — `kind` 가 `"responses"` 인 모델(pro 등급 · gpt-5.3-codex · `endpoint` 가 `"POST /v1/responses"`)은 `/v1/chat/completions` 로 못 불러요. Claude 줄은 `POST /v1/chat/completions` 이고 `/v1/messages` 로도 불러요 — 이 문은 Claude 만 받아요. > - `supports_effort` 가 `true` 인 GPT 는 생각한 토큰도 출력 상한(`max_tokens` · `max_completion_tokens`)에 들어가요 — 수백으로 두면 답이 비고 `finish_reason` 이 `"length"` 로 끝날 수 있으니 2,000 쯤에서 시작하고 `"length"` 면 올리세요. > - 목록 응답은 `{"object": "list", "data": [ … ]}`. 값 어림 — 한 번 값은 (입력 토큰 × `pricing.input_credits_per_mtok` + 출력 토큰 × `pricing.output_credits_per_mtok`) ÷ 100만 크레딧이에요(1 크레딧은 부가세 포함 2원어치예요). > - ❌ `x-should-retry: false` 응답을 반복문으로 다시 보내기 → ✅ 멈추고 `error.type` 을 확인하세요. 몸통은 OpenAI 형식 문이면 `{"error": {"type": "…", "message": "…", "code": "…"}}`, `/v1/messages` 면 `{"type": "error", "error": {"type": "…", "message": "…"}}` 예요 — 402 · 키 한도 · 강좌 몫 429 엔 `error.reason` 이 더 붙어요. 잠시 뒤 그대로 다시 보낼 실패엔 `Retry-After`(정수 초)가 대개 와요. > - ❌ `if "429" in str(e)` · `e.message` 로 분기 → ✅ Python openai 는 `e.type` · `e.body.get("reason")`, Node openai 는 `err.type` · `err.error.reason` — 429 는 키 한도 · 벤더 혼잡 · 강좌 몫 셋이라 상태 코드로 못 갈라요. Python Anthropic SDK 는 `except anthropic.APIStatusError as e:` 에서 `e.status_code` 와 `e.body["error"]["type"]`, Node 는 `err.status` 와 `err.error.error.type` 로 읽어요. 402 · 키 한도 429 의 갈래(`reason`)는 Python Anthropic SDK 면 `e.body["error"].get("reason")`, Node 면 `err.error.error.reason` 이에요. > - 남은 크레딧(지갑 전체)은 `GET https://oneport.kr/v1/credits` 의 `balance_credits` 예요(1 크레딧 아래를 버린 정수라 호출 앞뒤 차이로 쓴 몫을 세지 마세요 — 쓴 몫은 글 문 응답의 `usage.cost_credits` · 정산이 2초 안에 안 끝나면 그 칸 없이 와요). `GET https://oneport.kr/v1/key` 는 이 키에 건 한도(`month` · `day`)만 보여 주고 지갑 잔액은 없어요 — `month` · `day` 는 늘 객체이고 한도를 안 건 키면 `month.remaining_credits` · `day.remaining_credits` 가 null 이에요 · 그땐 지갑 잔액까지 써요. > - 하루 한도는 이미 쓴 몫이 한도에 닿았는지만 봐요 — 이번 달 · 강좌 한도는 이 요청 최대 몫까지 더해 재서 줄이면 통과할 수 있어요. 키 월 한도는 같은 API 키로 아직 끝나지 않은 호출 몫까지 더해 넘었으면 `error.reason` 이 `"held_by_others"` 로 와요. 묶음 처리 문(`/v1/batches`)은 없어요 — 한 건씩 보내요(동시에 보내도 되고 분당 횟수 제한도 없어요). > - 스트림 없이 부르면 답이 다 만들어져야 첫 응답이 와요 — 모델 회사로 보낸 뒤 120초 안에 안 오면 422 `upstream_execution_unconfirmed` 로 끝나요(모델 회사에서는 실행됐을 수 있어요). 그보다 긴 답은 `stream: true` 로 받으세요(스트림은 약 12분 50초에 끊겨요). SDK 시간 제한은 300초로 두세요(Python `OpenAI(…, timeout=300)` · Node `new OpenAI({ …, timeout: 300_000 })` — Node 는 밀리초 · SDK 동작). > - 첫 응답 120초 시계는 스트림이어도 같아요. 이 422 는 `x-should-retry: false` 로 와요 — 같은 요청을 자동으로 다시 보내지 마세요. stream: true 로 바꾸는 것도 새 생성이라 자동으로 하지 않아요. `Idempotency-Key` 를 실어 보낸 요청이면 받은 `x-gateway-status-url` 을 같은 API 키로 GET 조회하세요. `Idempotency-Key` 없이 보낸 요청엔 조회 주소가 안 오고 요청 ID 로 만든 주소로는 조회가 안 돼요 — 요청 ID 와 부른 시각을 admin@schoolorder.kr 로 알려 주세요. 요청 ID 는 머리글 `request-id`(같은 값이 `x-request-id`)와 오류 몸통 `error.request_id` 로 와요. 조회 주소는 `/v1/requests/` 꼴 상대 주소라 앞에 https://oneport.kr 를 붙여요. > - 고친 요청엔 새 Idempotency-Key 를 써요(같은 Idempotency-Key 로 본문을 바꾸면 409 `idempotency_conflict`). `Idempotency-Key` 를 실었으면 200 머리말을 받기 전의 연결 오류 · 시간 초과 뒤에 같은 Idempotency-Key · 같은 본문으로 다시 보내세요(몇 번 보내도 두 번 실행되지 않지만, 간격은 늘려 가며). 200 을 받은 뒤 끊긴 스트림은 잘린 답이라 같은 Idempotency-Key 는 409 예요 — 그때까지 쓴 토큰은 사용했고, 받은 글로 이어 받을 땐 새 Idempotency-Key 예요. > - 경계 사례는 이 장 전체 판(`https://oneport.kr/docs/changelog.full.md`)과 「에러」 장(`https://oneport.kr/docs/errors.md`)에 있어요.