오류 코드
Listings API HTTP 상태 코드, Listings 및 Social의 SYxxxxx 오류 코드, v4 API가 반환하는 3가지 오류 응답 형식입니다.
Listings API는 표준 HTTP 상태 코드를 사용하여 요청 결과를 알립니다. 오류 코드는 SY 접두사로 시작하며, 오류 message 문자열에 SYxxxxx: <human-readable reason> 형식으로 포함됩니다.
HTTP 상태 코드
HTTP status code summary
3가지 응답 형식
아래 절에서 설명하는 것처럼 대부분의 실패에는 최상위 수준이나 작업 결과 내부에 중첩된 errors 배열이 포함됩니다. 일부 실패는 대신 단일 error 객체를 반환합니다. 여기에는 요청 빈도 제한(429)과 일부 요청 수준의 실패(INTERNAL_SERVER_ERROR와 같은 code를 포함하는 400/500)가 해당합니다. 두 형식을 모두 검사합니다. errors는 배열이고 error는 객체입니다.
1. 요청 수준: 최상위 errors[]
인증, 권한 부여 및 잘못된 요청 형식으로 인한 실패는 작업이 실행되기 전에 처리를 중단합니다. 이러한 실패는 해당 4xx 상태(위 참조)를 반환하며, 오류는 응답의 최상위 수준에 포함됩니다.
{ "data": { "createLocation": null }, "errors": [{ "message": "SY90005: Invalid Token" }]}2. 쓰기 유효성 검사: 중첩된 data.<operation>.errors[]
그 밖의 형식에 문제가 없는 생성, 업데이트 또는 게시 요청은 HTTP 200을 반환합니다. 입력이 비즈니스 규칙을 위반하면 해당 작업 자체의 페이로드 아래 data.<operation>.errors에 중첩된 형태로 실패가 보고됩니다. 성공 시에도 이 배열은 존재하며 비어 있습니다("errors": []).
{ "data": { "createLocation": { "errors": [ { "message": "SY10126: City is Mandatory" }, { "message": "SY10010: state_iso" } ], "location": null } }}3. 게이트웨이 수준: 최상위의 단일 error 객체
요청 빈도 제한과 예기치 않은 게이트웨이 오류는 변환 전에 처리를 중단하고, code, message 및 correlation_id를 포함하는 error 객체 1개를 반환합니다. 429 본문은 아래 rate_limited를 참조합니다.
쓰기 작업에서는 값이 채워진 data.<operation> 객체가 있는 200 응답이라도 항상 data.<operation>.errors를 확인합니다. 쓰기 작업은 부분적으로 실패할 수 있으며, 해당 실패가 여기에 보고될 수 있습니다.
402 Payment Required 응답에는 error 래퍼가 없습니다. code, message, doc_url 및 납부할 청구서가 있을 때의 pay_url은 최상위 수준에 있습니다. 아래 payment_required를 참조합니다.
쓰기 작업은 부담 없이 재시도할 수 없습니다
v4 API는 Idempotency-Key를 지원하지 않습니다. 해당 헤더는 무시되며, 반복된 쓰기 작업을 감지하는 엔드포인트는 없습니다. 생성, 업데이트 또는 게시 호출이 시간 초과되거나 5xx를 반환하더라도 서버에서는 이미 변경 사항이 커밋되었을 수 있으므로, 확인 없이 재시도하면 사업장, 게시물 또는 리뷰 답글이 중복 생성될 수 있습니다.
읽기 작업은 대기 시간을 점차 늘리며 자유롭게 재시도합니다. 쓰기 작업은 먼저 다시 읽어 확인합니다. 직접 관리하는 키(storeId, 매장 코드, 상호작용의 답글 목록)로 레코드를 조회하고, 실제로 존재하지 않을 때만 호출을 반복합니다.
일반적인 코드
Common SY error codes
SY10xxx 범위의 유효성 검사 코드는 특정 입력 필드에 해당하며, message는 유효성 검사를 통과하지 못한 필드나 규칙을 명시합니다. SY90xxx 범위의 인증 및 권한 부여 코드는 요청 수준의 코드이며, 해당 상태와 함께 최상위 수준에 반환됩니다.
연결된 계정 코드
SY810xx 범위의 코드는 게시 플랫폼의 등록 정보를 가져오거나 연결하는 Connected Accounts 엔드포인트에서 반환됩니다. 이 코드는 HTTP 200 응답의 본문에 중첩되어 반환되므로(위의 응답 형식 2), 상태가 성공이더라도 data.<operation>.errors를 확인합니다.
SY810xx connected-account and import codes
Social 코드
SY950xx 범위의 코드는 브랜드, 연결, 소셜 게시물에 관한 Social 엔드포인트에서 발생합니다. 연결된 계정 관련 코드와 마찬가지로, 이 코드들은 HTTP 200의 응답 본문에 중첩된 형태로 전달되므로 상태가 성공이더라도 data.<operation>.error를 확인하고 일괄 처리 경로에서는 data.<operation>.errors도 확인해야 합니다.
SY950xx Social codes
SY95042와 SY95044는 입력 오류가 아닌 이용 권한 오류이므로, 요금제를 변경하지 않고 다시 시도하면 동일하게 실패합니다. SY95045, SY95046, SY95049, SY95052는 다음 요청에서 수정할 수 있는 입력 오류입니다.
Listings 이용 권한 코드
Listings plan codes
rate_limited
429 Too Many Requests: 계정이 요금제의 요청 빈도 제한을 초과했습니다. 본문은 표준 오류 응답이며, retry_after_seconds 힌트, 지원 요청 시 명시할 correlation_id, 이 섹션으로 연결되는 doc_url을 포함합니다:
{ "error": { "code": "RATE_LIMITED", "message": "Too many requests. Slow down.", "retry_after_seconds": 30, "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#rate_limited" }}retry_after_seconds에 지정된 시간(Retry-After 헤더가 있으면 해당 헤더에 지정된 시간) 동안 기다린 후 지수 백오프를 적용하여 재시도합니다. 요금제별 제한과 백오프 구현 예시는 요청 빈도 제한을 참조합니다.
payment_required
402: 이 계정의 마지막 결제가 처리되지 않아 모든 /api/v4 엔드포인트가 일시 중지되었습니다. 미결제 청구서의 Stripe 페이지가 있으면 본문에 해당 페이지를 가리키는 pay_url이 포함되며, X-Error-Code 응답 헤더에도 동일한 code가 포함됩니다. 대시보드의 청구 페이지는 계속 열 수 있으며, 여기에서 결제할 수 있습니다.
{ "code": "payment_required", "message": "This account has an unpaid invoice, so API access is paused. Pay the invoice to restore access.", "pay_url": "https://invoice.stripe.com/i/acct_123/test_abc", "doc_url": "https://listingsapi.com/docs/error-codes#payment_required"}마지막 미결제 청구서의 결제가 완료되면 1분 이내에 액세스가 복구됩니다. 최초 결제 실패 후 3일이 지나도 청구서가 미결제 상태이면 Listings 구독이 취소되고 계정의 사업장이 보관 처리됩니다. 계정에 활성 Social 구독도 있으면 Social 액세스는 유지되며, 그렇지 않으면 계정이 폐쇄되고 해당 계정의 API 키가 더 이상 작동하지 않습니다.
social_payment_required
402: Social 구독의 마지막 결제가 처리되지 않아 Social 엔드포인트(/api/v4/social/*)가 일시 중지되었습니다. Listings 엔드포인트는 계속 작동합니다. 본문에는 payment_required와 동일한 필드가 포함되며, "code": "social_payment_required"가 함께 제공됩니다. 최초 결제 실패 후 3일이 지나도 청구서가 미결제 상태이면 Social 구독이 취소되고 계정의 브랜드가 보관 처리됩니다. Listings 구독이 없는 계정은 폐쇄되며, 해당 계정의 API 키가 더 이상 작동하지 않습니다.
개발자 포털 제어 영역 오류
개발자 포털의 계정 및 키 관리 엔드포인트(대시보드 자체 API 경로)는 위의 REST errors[] 형식과 구분되는 단일 구조의 오류 응답을 반환합니다. 각 code에는 correlation_id와 이 문서의 해당 섹션으로 연결되는 doc_url이 포함됩니다.
{ "error": { "code": "AUTH_INVALID_KEY", "message": "Session is invalid or expired.", "correlation_id": "9f2c1e64-2b1a-4b0e-9f1a-2c7d5e8a1b3c", "doc_url": "https://listingsapi.com/docs/error-codes#auth_invalid_key" }}auth_missing_key
401: 자격 증명이 제공되지 않았습니다. 다시 로그인하거나 키를 Authorization: API <your-key> 형식으로 전송합니다.
auth_invalid_key
401: 세션 또는 키가 유효하지 않거나 만료되었습니다. 다시 인증하거나 대시보드에서 키를 재발급합니다.
auth_insufficient_scope
403: 자격 증명은 유효하지만 이 작업을 수행할 권한이 없습니다. 읽기 권한 범위의 키로는 쓰기 엔드포인트를 호출할 수 없으므로, 필요한 경우 쓰기 키를 발급합니다.
not_found
404: 요청한 리소스 또는 ID로 지정한 리소스가 존재하지 않습니다.
conflict
409: 요청이 리소스의 현재 상태와 충돌합니다(예: 이미 폐기된 키를 다시 폐기하는 경우).
validation_failed
422: 요청 본문이 유효성 검사를 통과하지 못했습니다. 응답의 field와 details에 문제가 있는 입력이 명시됩니다.
internal_error
500: 예기치 않은 서버 측 오류가 발생했습니다. 읽기 작업은 지수 백오프를 적용하여 재시도하고, 쓰기 작업은 먼저 해당 레코드를 다시 조회합니다(쓰기 작업은 부담 없이 재시도할 수 없습니다 참조). 지원팀에 문의할 경우 correlation_id를 명시합니다.
dependency_unavailable
503: API가 의존하는 서비스를 일시적으로 사용할 수 없습니다. 백오프를 적용하여 재시도합니다.
429에 대해서는 위의 rate_limited를 참조합니다.
코드에서 오류 처리하기
먼저 HTTP 상태를 확인한 다음, 쓰기 작업의 경우 응답 본문에 중첩된 errors 배열이 있는지 확인합니다:
from listingsapi import APIError, ListingsAPI client = ListingsAPI(api_key=os.environ["LISTINGSAPI_KEY"]) try: location = client.locations.create(input=payload)except APIError as e: # Raised for a non-2xx status (AuthenticationError, ValidationError, and # so on) and for an error payload returned inside a 200 body. raise RuntimeError(f"Listings API error: {e}") from e원시 HTTP API를 직접 사용할 때도 상태 코드, 응답 페이로드 순서로 동일한 2가지 항목을 명시적으로 확인합니다:
resp = requests.post( "https://listingsapi.com/api/v4/locations", headers={"Authorization": f"API {os.environ['LISTINGSAPI_KEY']}"}, json=payload, timeout=30,)resp.raise_for_status()body = resp.json() op = (body.get("data") or {}).get("createLocation") or {}if op.get("errors"): messages = [e["message"] for e in op["errors"]] raise RuntimeError(f"Listings API error: {messages}")Python SDK는 이 2가지 확인을 모두 수행합니다. 각 HTTP 상태를 해당 타입의 예외에 매핑하고, 200 본문 안에 오류 페이로드가 반환된 경우에도 예외를 발생시킵니다.