Skip to main content

API 개요

Log Query API는 계정 아래에서 수행된 모든 API 호출의 상세 기록을 반환합니다. 여기에는 사용된 모델, 실제 청구 금액, 지연 시간, 호출이 스트리밍되었는지 여부, 그리고 호출이 실패했을 때의 오류 코드가 포함됩니다. 이 API는 잔액 조회 API를 보완합니다. 잔액 조회는 남은 크레딧이 얼마인지 알려주고, 로그 조회는 그것이 어디로 갔는지 알려줍니다. 세 가지 대표적인 사용 사례는 다음과 같습니다:

자동 대사

시간 범위나 모델별로 실제 지출을 집계하고 자체 과금 내역과 대조합니다

셀프 서비스 문제 해결

실패한 요청의 오류 코드를 확인하여 매개변수 문제와 상위 시스템 문제를 구분합니다

지원 티켓

정확한 호출을 특정할 수 있도록 지원팀에 request_id를 제공하십시오
로그는 콘솔의 Logs 페이지에서도 볼 수 있습니다. 이 API는 동일한 데이터에 대한 프로그래밍 방식의 진입점으로, 자동 대사, 예약된 내보내기, 또는 자체 모니터링에 활용하는 용도입니다. 수동 확인은 콘솔을 사용하십시오 — 내 호출 기록을 보는 방법을 참조하십시오.
권장 사용법: 하루에 한 번 동기화하고 로그를 자체 데이터베이스에 저장하십시오.이 API는 반복적인 실시간 조회가 아니라 예약된 증분 내보내기를 위해 설계되었습니다:
  • 하루에 한 번 실행하여 마지막 동기화 이후 생성된 기록만 자체 데이터베이스나 CSV 파일로 가져오십시오
  • 요청당 더 많이 가져오십시오: pageSize은 최대 5000까지 올라갑니다 — 기본값 10으로 두지 마십시오. 여기서의 함정은 아래의 매개변수 참고사항을 참조하십시오
  • 대량 백필(한 번에 3개월치를 가져오기) 용도로 사용하지 말고, UI에서 실시간 페이지네이션을 구동하는 데도 사용하지 마십시오
  • 동시에 호출하지 마십시오 — 페이지는 순차적으로 넘기며, 각 페이지 사이에 약 1초를 두십시오
  • 각 시간 범위는 하루 이내로 유지하십시오. 트래픽이 많은 계정은 시간 단위로 나누십시오
왜 그런지에 대해서는 아래의 성능 노트 섹션을 참조하십시오. 윈도우가 오래될수록, 그리고 페이지네이션이 깊을수록 각 요청 비용이 더 커집니다. 서버 측 한도를 넘으면 오류가 반환되며, 같은 매개변수로 다시 시도해도 더 빨라지지 않습니다. 이 페이지의 Python 예제는 이미 이 패턴을 따르고 있으며 하루 한 번 실행하는 cron 작업에 그대로 넣을 수 있습니다.

개인 액세스 token 발급 방법

Log Query API는 개인 액세스 token(nap_(으)로 시작)으로 인증하며, 이는 API 키와 동일하지 않습니다(이 페이지 하단의 중요 참고 사항 참조).
1

개인 액세스 token 열기

api.apiyi.com/account/profile의 프로필 페이지로 이동합니다. 계정 옵션에서 개인 액세스 token → token 생성을 클릭합니다.
2

권한 선택

이 API는 사용량 및 개인 기록 · 읽기 권한만 필요합니다. 매일 실행되는 예약 작업의 경우 더 긴 만료 기간을 선택하십시오. 기본값은 30일이며, token이 만료되면 스크립트에서 401 오류가 발생합니다.
3

IP 허용 목록 설정(선택 사항)

동기화 스크립트가 고정 IP를 사용하는 서버에서 실행되는 경우 권장합니다. 허용 목록은 생성 후 수정할 수 없습니다. 먼저 허용 목록 없이 스크립트가 정상 작동하는지 확인한 다음, 허용 목록을 포함한 별도의 프로덕션 token을 생성하십시오.
개인 액세스 token 생성: 이름, 만료 기간, IP 허용 목록 및 권한
레거시 시스템 token은 2026-11-11 (UTC+8)에 폐기될 예정입니다. “계정 옵션 - 시스템 token”에서 생성된 AccessToken은 그때까지 계속 작동합니다. 해당 날짜 이후에는 401 ACCESS_TOKEN_LEGACY_RETIRED을 반환합니다. 이용 현황을 검토하여 해당 일정을 연장할 수도 있으나, 지금 개인 액세스 token으로 전환하는 것을 권장합니다. APIYI_SYS_TOKEN의 값만 변경하면 되며, 아래 스크립트는 그대로 유지됩니다. 개인 액세스 token이란 무엇인가요?를 참조하십시오.

API 정보

요청 세부 정보

요청 헤더

쿼리 매개변수

시간 범위는 필수로 간주하십시오.이 엔드포인트는 실제로 이 두 매개변수를 강제하지 않습니다. 없어도 호출은 성공합니다. 하지만 이를 생략하면 서버는 계정의 최신 레코드부터 거꾸로 전체 기록을 검색하며, 호출 기록이 많은 계정은 서버 측 제한에 걸려 느린 응답 대신 오류를 받게 됩니다.이 페이지에서 가장 쉽게 저지르는 실수이자 가장 직접적인 결과를 낳는 실수입니다. 서버가 호출을 거부하기 때문이 아니라, 실패 양상이 알아차리기 어렵기 때문에 Required로 표시합니다. 누락된 매개변수를 보고하지 않고 타임아웃을 보고합니다.
pageSize는 이 엔드포인트에서 유일한 camelCase 매개변수입니다. 이를 page_size로 잘못 적어도 조용히 무시됩니다.나머지 모든 매개변수(model_name, token_name, start_timestamp, request_id, …)는 snake_case를 사용합니다. 이 항목만은 그렇지 않습니다. 잘못 지정해도 오류가 발생하지 않습니다. 서버는 해당 매개변수를 없는 것으로 처리하고 페이지당 레코드 수 기본값 10을 사용합니다, 이로 인해 “상한이 10이다” 또는 “이 기간에 호출을 10번만 했다”로 오해하기 쉽습니다.
5000을 초과하면 조용히 잘리는 대신 명확한 오류가 발생합니다.
이 엔드포인트에서 가장 효과적인 최적화는 pageSize의 값을 키우는 것입니다. 페이지당 레코드 10개일 때 하루 500,000건의 호출이 있는 계정은 50,000개의 요청이 필요하지만, 페이지당 5000개일 때는 100개면 됩니다. 요청 수가 두 자릿수 규모로 줄어들고, 그에 따라 페이지네이션 오프셋도 감소합니다 — 아래 성능 참고 사항을 보십시오.5000개 레코드 페이지는 gzip으로 압축하면 대략 700 KB이며 약 2.5초가 걸립니다. 대역폭이나 메모리가 빠듯하다면, 1000가 무난한 중간 지점입니다.

성능 참고 사항

단일 요청의 비용은 고정되어 있지 않습니다. 세 가지 요인에 따라 달라집니다. 이 규칙을 따르면 API는 빠르게 동작하지만, 무시하면 서버 측 60초 쿼리 제한에 걸려 오류가 반환됩니다. 실용적인 규칙 네 가지입니다.
  1. 항상 start_timestamp와 end_timestamp를 전달하십시오. 윈도우를 생략하는 것은 이 API를 호출하는 가장 비싼 방법입니다.
  2. pageSize를 늘리십시오. 이건 쉽습니다. 페이지당 10건에서 1000–5000건으로 늘리면 요청 횟수가 두 자릿수 규모로 줄어들고, 오프셋도 함께 줄어듭니다.
  3. 오프셋을 깊게 하기보다 윈도우를 줄이십시오. 비용이 드는 것은 “몇 번째 페이지인지”가 아니라 “그 위치에 도달하기 위해 몇 개의 레코드를 건너뛰었는지”이며, 이는 초선형적으로 증가합니다. 큰 윈도우 하나를 끝까지 페이지 처리하기보다 24개의 1시간 윈도우로 나누어 각 윈도우가 다시 오프셋 0에서 시작하게 하십시오.
  4. 히스토리를 한 번 백필하고 저장한 뒤, 이후에는 증가분만 동기화하십시오. 오래된 데이터는 최근 데이터보다 조회 비용이 훨씬 더 크므로, 같은 히스토리를 반복해서 다시 읽는 것은 순수한 낭비입니다.
윈도우가 pageSize=1000에서 여전히 수십 페이지를 차지한다면, 해당 기간의 호출량이 높다는 뜻입니다. 윈도우를 반으로 나누고 각 절반을 별도로 가져오십시오. 이렇게 하는 편이 더 깊이 페이지 처리하는 것보다 훨씬 빠릅니다. 아래 Python 예제의 MAX_PAGES 상수가 바로 이 작업을 수행합니다.

60초는 엄격한 제한이며, 초과하면 오류가 반환됩니다

서버는 단일 쿼리를 60초로 제한합니다. 그 시간을 넘으면 느린 응답을 받는 것이 아니라 — 오류를 받게 되며, 이미 소요한 시간으로는 데이터를 전혀 얻지 못합니다. 다음 세 가지 패턴이 이를 유발할 가능성이 높습니다. 재시도하며 운을 기대하기보다 아예 피하십시오. 같은 파라미터로 다시 시도해도 더 빨라지지 않습니다. 그냥 60초가 한 번 더 들 뿐입니다. 올바른 대응은 시간 윈도우를 좁히거나, pageSize를 늘려 페이지 수를 줄이는 것입니다. 어느 쪽이든, 호출당 서버가 처리해야 하는 데이터를 더 적게 만들어야 합니다.

로그 유형

지출을 계산할 때는 항상 type=2을 전달하십시오. 이를 지정하지 않으면 충전 및 시스템 부여 기록도 반환됩니다. 해당 기록의 quota은 0이지만 model_name 및 token_name도 비어 있으므로, 단순히 합산하거나 모델별로 그룹화하면 잘못된 결과가 생성됩니다.계정에서 비동기 동영상 모델(Seedance 등)을 사용하는 경우 type=11도 가져오십시오. 작업이 실패하면 사전 청구 금액이 음수 환불 항목으로 반환되므로, type=2만 합산하면 해당 사전 청구 금액이 지출로 계산됩니다.

응답 세부 정보

성공 응답 예시

주요 응답 필드

other 필드는 중첩 객체가 아닌 JSON 문자열이므로 한 번 더 파싱해야 합니다 (Python에서는 json.loads(), JavaScript에서는 JSON.parse()). 여기에는 billing_type, request_path(실제로 호출된 엔드포인트), group_ratio, model_ratio 및 usage가 포함됩니다.비동기 동영상 작업의 정산 항목에는 final_quota(작업의 최종 총액), original_quota (제출 시 청구된 사전 금액), adjustment_quota(이 항목의 차액) 및 actual_tokens도 포함됩니다. 아래 자주 묻는 질문을 참조하십시오.

쿼터 변환

변환 규칙

500,000 쿼터 = $1.00 USD
공식: USD 금액 = quota ÷ 500,000 예시:
  • quota: 7500 → $0.015 USD
  • quota: 22500 → $0.045 USD
  • quota: 18 → $0.000036 USD
이는 잔액 조회 API에서 사용하는 변환과 동일하므로, 두 값은 직접 일치합니다.

오류 응답

HTTP 401 - 인증 실패

원인: token이 유효하지 않거나 만료 또는 삭제되었거나, sk-(으)로 시작하는 API 키를 개인 액세스 token으로 잘못 사용했습니다. 계정 비밀번호, 2단계 인증 또는 패스키를 변경하면 모든 개인 액세스 token이 해지됩니다. 해결 방법: 콘솔에서 새 개인 액세스 token을 생성하십시오. 다른 두 가지 401 응답에는 명시적인 메시지가 포함됩니다:

HTTP 403 - 권한 거부됨

원인: 개인 액세스 token에 사용량 및 개인 기록 · 읽기 권한이 없습니다. 해당 권한을 가진 새 token을 생성하십시오. 권한은 생성 후 변경할 수 없습니다.

코드 예시

cURL 예시 (단일 페이지, 빠른 확인)

--compressed 옵션은 필수입니다. API가 gzip으로 압축된 콘텐츠를 반환하기 때문입니다. 이 옵션이 없으면 출력이 깨져서 표시됩니다.
token이 정상 작동하는지 확인하는 데 사용하십시오. 실제 대사 작업에는 아래의 일일 동기화 스크립트를 사용하십시오.

Python 예제: 일일 증분 동기화(크론 작업으로 바로 사용할 수 있음)

이것은 권장 표준 사용법입니다: 하루에 한 번 실행하여 마지막 동기화 이후 새로 생긴 내용만 가져와 로컬 SQLite 데이터베이스에 기록합니다. 다시 실행해도 안전합니다(기록은 request_id에서 중복 제거됨). 실행이 중간에 중단되어도 중단된 지점에서 재개됩니다.
샘플 출력:
데이터가 로컬에 있으면, 모델별, 일별, token별로 필요한 모든 분석은 자체 데이터베이스를 대상으로 실행되므로 그것을 위해 다시는 API를 조회할 필요가 없습니다. 이는 훨씬 더 빠르며, 이미 보존 기간을 벗어나 오래된 데이터를 원하게 되는 문제도 피할 수 있습니다.

Node.js 예제(단일 시간 창)

같은 아이디어입니다: 시간을 기준으로 분할하고, 순차적으로 페이지를 가져오며, 페이지네이션이 너무 깊어지면 창을 줄입니다.
Python requests 라이브러리와 Node.js fetch API는 모두 gzip을 자동으로 압축 해제하므로, 별도의 구성이 필요하지 않습니다. curl만 명시적인 --compressed 플래그가 필요합니다.

일반적인 시나리오

일일 정산(권장 방식)

위의 Python 스크립트를 하루에 한 번 실행하도록 예약하고 로그를 로컬 데이터베이스에 적재하십시오. 필요한 모든 세부 분석—총 지출, 모델별, token별—은 결국 자체 데이터베이스를 대상으로 하는 SQL 쿼리입니다. 이 방식이 적절한 이유는 세 가지입니다. 로컬 쿼리는 빠르고, 로그 보존 기간의 영향을 받지 않으며, 오래된 기록을 반복해서 다시 읽느라 API가 느려지는 일도 피할 수 있습니다. 한 모델의 기록만 동기화하려면 요청에 model_name 매개변수를 추가하십시오.

실패한 호출 찾기

데이터가 로컬에 있으면 자체 테이블을 직접 조회하십시오:
게이트웨이에서 거부된 요청(잘못된 매개변수 등)은 quota가 0이며 과금되지 않습니다. 로그의 error_code은 “호출이 실패했습니다”와 “호출은 성공했지만 결과가 마음에 들지 않았습니다”를 구분하는 데 도움이 됩니다.

지원용 요청 ID 제공

로그에서 문제가 되는 호출을 찾아 지원팀에 request_id를 제공하십시오. 그러면 처음부터 끝까지 정확한 요청을 식별할 수 있으므로, “어떤 모델에 대한 호출이 특정 시점쯤 실패했습니다”라고 설명하는 것보다 훨씬 효율적입니다.

자주 묻는 질문

먼저 다음 세 가지를 확인하십시오. 거의 모든 느린 쿼리는 이 중 하나에서 발생합니다.
  1. start_timestamp 및 end_timestamp를 전달하고 있습니까? 시간 범위를 생략하는 것은 이 API를 호출하는 가장 비용이 큰 방법입니다. 서버가 전체 기록을 검색합니다.
  2. 범위가 너무 오래되었거나 너무 넓습니까? 한 달 전 데이터를 쿼리하는 것은 어제 데이터를 쿼리하는 것보다 훨씬 많은 비용이 듭니다. 범위는 하루 미만으로 유지하고, 대용량의 경우 시간 단위로 분할하십시오.
  3. p가 수천 개에 도달했습니까? 페이지네이션 비용은 초선형적으로 증가합니다. 해결 방법은 하나의 큰 범위 내에서 더 깊이 페이지를 탐색하는 것이 아니라, 각 범위에 수십 페이지만 필요하도록 시간 범위를 줄이는 것입니다.
동일한 파라미터로 재시도해도 더 빨라지지 않습니다. 시간 초과 시에는 동일한 요청을 반복하는 대신 위와 같이 파라미터를 조정하십시오. 단순 재시도는 다시 기다리게 할 뿐입니다.
열 번 중 아홉 번은 파라미터의 철자가 snake_case인 page_size로 작성된 경우입니다.올바른 표기는 camelCase인 pageSize입니다. 이 엔드포인트에서 유일한 camelCase 파라미터이며, 나머지 모든 항목(model_name, token_name, start_timestamp, …)은 snake_case이므로 실수하기 쉽습니다. 오류는 발생하지 않으며, 서버는 해당 파라미터가 없는 것으로 처리하고 페이지당 10개 레코드로 대체합니다.
최대값은 5000이며, 이를 초과하면 명확한 오류가 반환됩니다. 대용량의 경우에도 응답이 빈 배열을 반환할 때까지 페이지네이션(p=0, p=1, …)해야 합니다. 위의 Python 및 Node.js 예제에는 이미 이 과정이 포함되어 있습니다.
예. request_id를 전달하면 해당 레코드만 반환됩니다.
특정 호출 하나를 조사할 때는 시간 범위를 가져와 직접 필터링하는 것보다 훨씬 빠릅니다.
아닙니다. 일부 필드는 플랫폼 내부 정보를 담고 있으며 일반 계정 관점에서는 비어 있거나 0입니다. 이는 예상된 동작이며, 정산 또는 문제 해결에 필요한 필드에는 영향을 주지 않습니다. quota, model_name, error_code 및 request_id는 모두 완전히 채워집니다.
API는 그룹 식별자를 반환하는 반면, 콘솔은 그룹의 레이블을 표시합니다. 이 둘은 다를 수 있습니다. 예를 들어 API는 default를 반환하지만 콘솔에는 Default가 표시됩니다.전체 매핑은 공개 엔드포인트 https://api.apiyi.com/api/pricing의 usable_group 필드에서 제공되며, 식별자를 레이블에 매핑합니다. 보고서를 콘솔과 일치시키려면 이 매핑을 직접 적용하십시오.
quota를 사용하십시오. 이는 호출에 대해 실제로 차감된 금액이며 정산에 적합한 유일한 필드입니다. 이미지 및 동영상 생성과 같은 호출별 가격 책정 모델의 경우, 응답의 token 수는 가격 책정에 참여하지 않는 플레이스홀더 값일 수 있습니다. 이러한 모델은 other.billing_type에 by_count를 보고합니다.
최근 30일만 쿼리할 수 있다고 가정하여 동기화 로직을 설계하십시오.실제로 쿼리 가능한 범위는 일반적으로 더 길지만, 보존 기간에 대해서는 어떠한 보장도 하지 않습니다. 이는 로그 정리 정책에 따라 변경되며, 변경 사항은 별도로 공지되지 않습니다. 30일을 계획의 최저 기준으로 삼으면 정책이 바뀌어도 정산이 중단되지 않습니다.또한 범위가 오래될수록 쿼리 비용이 더 커집니다. 데이터가 여전히 존재하더라도 해당 데이터에 도달하는 속도는 훨씬 느립니다.따라서 올바른 패턴은 하루에 한 번 자체 데이터베이스로 동기화하고, 과거 분석은 로컬에서 수행하는 것입니다. 장기적으로 보관해야 하는 항목은 직접 아카이브하십시오. 이 API로 다시 가져올 수 있다고 의존하지 마십시오.
원인: API는 gzip 압축 콘텐츠(Content-Encoding: gzip)를 반환하지만 curl이 이를 압축 해제하지 않습니다.해결 방법: --compressed 플래그를 추가하십시오.
Python requests 라이브러리와 Node.js fetch API는 자동으로 압축을 해제합니다.
비동기 동영상 작업(Seedance 및 유사 작업)은 ‘제출 시 선차감, 완료 시 차액 정산’ 방식으로 과금되므로 동영상 하나에 두 개의 항목이 남습니다. 즉, 선차감 항목(completion_tokens는 0, request_id 존재)과 정산 항목(completion_tokens는 실제 사용량, request_id는 비어 있음, quota는 차액만 해당)입니다. 어느 항목에도 task_id가 포함되지 않으므로, 이 API는 항목을 작업과 연결할 수 없습니다.동영상의 실제 비용을 확인하려면 task_id로 작업 API를 쿼리하십시오. 해당 API의 quota는 두 항목의 합계입니다.
해당 API의 페이지네이션 파라미터는 이 API와 반대로 snake_case page_size를 사용하며 p는 1부터 시작합니다. 실패한 작업도 quota에 선차감 내역이 표시되지만 실제 비용은 0입니다(로그에는 음수 type=11 환불 항목이 포함됩니다). 전체 안내: task_id로 Seedance 동영상의 실제 비용을 조회하는 방법.
아닙니다. 로그 쿼리 엔드포인트는 쿼터를 소모하지 않습니다.

중요 참고 사항

개인 액세스 token은 API 키가 아니며, 두 가지는 상호 대체할 수 없습니다
  • API 키(sk-로 시작)는 /v1/* 추론 엔드포인트용입니다. /api/log/self에 대해 사용하면 401이 반환됩니다.
  • 개인 액세스 token(nap_로 시작)은 /api/* 관리 엔드포인트용이며 모델을 호출할 수 없습니다.
대사 스크립트의 token에는 “Usage & personal records · Read” 권한만 부여하십시오. 설정할 수 있다고 해서 다른 권한까지 추가하지 마십시오. 코드 대신 시크릿 관리자에 저장하고, 저장소에 절대 커밋하지 마십시오. 그리고 만료되기 전에 교체하십시오.
로그 응답에는 본인의 API 키가 평문으로 포함되어 있습니다각 로그 레코드에는 호출을 수행한 token에 대한 정보가 포함되어 있습니다. 원시 로그 응답을 공개 장소에 붙여넣거나, 스크린샷으로 공유하거나, 제3자에게 전달하지 마십시오 — 내보내기 전에 민감한 필드를 제거하십시오.특히 이 평문에는 sk- 접두사가 포함되어 있지 않으므로 일반적인 시크릿 스캐너가 이를 감지하지 못할 수 있습니다. 자동화된 검사에만 의존하지 마십시오.
권장 호출 패턴
  • 하루에 한 번 동기화하십시오 — 더 자주 실행할 필요가 없으며, 실행할 때마다 새로운 데이터만 가져옵니다.
  • 기본값인 10 대신 pageSize을 1000~5000으로 사용하십시오 — 다른 모든 항목을 합친 것보다 이 설정이 더 중요합니다.
  • 페이지 사이에 약 1초 간격을 두고 순차적으로 호출하십시오. 절대 동시에 실행하지 마십시오.
  • 클라이언트 타임아웃을 60초로 설정하십시오(서버 측 쿼리 제한도 60초입니다).
  • 각 시간 범위를 1일 이하로 유지하십시오. 호출량이 많은 계정의 경우 시간 단위로 분할하십시오.
  • 타임아웃 발생 시 시간 범위를 줄인 후 재시도하십시오 — 동일한 조건으로 재시도해도 빨라지지 않습니다.
이는 엄격한 쿼터가 아니며, 본인의 데이터를 가장 빠르게 가져올 수 있는 방법일 뿐입니다. 이 패턴을 준수하면 일반적인 계정은 1분 이내에 하루 치 전체 로그를 동기화할 수 있으며, 하루에 수십만 건의 호출을 수행하는 대규모 계정이라도 약 100건 정도의 요청만 필요합니다.
향후 이 엔드포인트에 요청 제한을 도입할 권리를 보유합니다.현재는 요청 제한이 없지만, 예약된 작업을 “무제한”을 전제로 설계하지 마십시오. 위의 패턴(하루에 한 번, 순차 실행, 큰 pageSize)을 준수하면 향후 요청 제한이 도입되더라도 영향을 받지 않습니다.

관련 문서