에러 코드
페이싱크 v2 API 응답의 숫자 code 값마다 HTTP 상태와 발생 조건을 정리했어요.
v2 API 응답의 code는 처리 결과를 나타내는 숫자 문자열이에요. 앞자리로 분류를 알 수 있어요. 예를 들어 22로 시작하는 여섯 자리 코드는 주문, 24로 시작하는 코드는 현금영수증 오류예요.
{
"code": "220003"
}
분기 처리는 HTTP 상태가 아니라 code로 하세요. 같은 HTTP 상태에도 여러 코드가 있어요. 엔드포인트별로 나올 수 있는 코드는 각 API 페이지에도 적혀 있어요. v1 API의 문자열 코드는 v1 에러 코드를 참고하세요.
성공
code |
HTTP | 설명 |
|---|---|---|
10001 |
200 | 요청을 처리했어요. 주문을 만들 때도 200이에요. |
인증과 권한
code |
HTTP | 설명 |
|---|---|---|
80001 |
401 | Authorization 헤더가 Bearer <키> 형식이 아니에요. |
80003 |
401 | Authorization 헤더가 없어요. |
290006 |
401 | API 키가 틀렸거나, 만료됐거나, 삭제됐거나, 꺼져 있어요. |
380009 |
401 | 연결된 앱의 액세스 토큰이 틀렸거나, 고객이 연결을 끊었어요. |
80002 |
403 | API 키의 계좌 범위 밖의 주문이나 입금에 접근했거나, API 키로 쓸 수 없는 요청이에요. |
80008 |
403 | API 키로 쓸 수 없는 대시보드 전용 요청이에요. |
290007 |
403 | 읽기 전용 API 키로 쓰기 요청을 보냈어요. |
380010 |
403 | 연결된 앱의 액세스 토큰에 이 요청에 필요한 스코프가 없어요. |
공통 검증
code |
HTTP | 설명 |
|---|---|---|
30001 |
422 | offset이 없거나 0보다 작아요. |
30002 |
422 | limit이 없거나 0 이하예요. |
40001 |
403 | limit이 100을 넘어요. |
30004 |
422 | dateFrom이나 dateTo가 YYYY-MM-DD 형식이 아니에요. |
30005 |
422 | dateFrom이 dateTo보다 늦어요. |
30007 |
422 | JSON 본문을 읽을 수 없거나, 필수 필드가 없거나, 필드 타입이 틀렸어요. |
30009 |
422 | 수정 요청에 바꿀 필드가 하나도 없어요. |
리소스 없음 (404)
code |
HTTP | 설명 |
|---|---|---|
20013 |
404 | 입금이 없어요. |
20014 |
404 | 주문이 없어요. |
20015 |
404 | 현금영수증이 없어요. |
다른 워크스페이스의 리소스도 없는 것으로 보고 404가 와요.
주문
code |
HTTP | 설명 |
|---|---|---|
220001 |
422 | 주문 ID 형식이 틀렸어요. |
220002 |
422 | customer.name이 1~16자가 아니거나 공백이 있어요. |
220003 |
422 | amount가 0 이하예요. |
220004 |
422 | customer.email이 5~255자가 아니거나 이메일 형식이 아니에요. |
220005 |
422 | customer.phoneNumber가 숫자 10~11자리가 아니에요. |
220006 |
422 | 만료 시각이 지났거나 365일 뒤를 넘어요. expiresAt과 expireAfterDays를 함께 보내도 이 코드가 와요. |
220007 |
422 | cashReceipt.type이 없는 값이거나 identifier가 형식에 맞지 않아요. |
220008 |
422 | metadata가 5쌍을 넘거나, 키가 비었거나 64자를 넘거나, 값이 1024자를 넘어요. |
220009 |
422 | bankAccountIds에 형식이 틀렸거나 없는 계좌 ID가 있어요. |
220010 |
409 | 입금자명과 금액이 같고 받을 계좌가 겹치는 결제 대기 주문이 이미 있어요. data에 기존 주문의 invoiceId와 number가 와요. 주문 충돌 규칙 참고 |
220011 |
409 | 지금 상태에서 할 수 없는 일이에요. 결제 대기가 아닌 주문을 수정하거나, 이미 결제됐거나 취소된 주문을 결제 완료 처리하거나 취소하려고 했어요. |
220012 |
422 | status 필터 값이 목록에 없어요. |
220013 |
422 | source 필터 값이 목록에 없어요. |
220017 |
422 | due 필터 값이 목록에 없어요. |
220018 |
422 | bankAccountIds에 1원 인증을 마치지 않은 계좌가 있어요. |
220019 |
422 | createdBy 필터 값이 SYSTEM, 계정 ID, API 키 ID가 아니에요. |
220020 |
422 | 취소 사유가 200자를 넘어요. |
220022 |
409 | 입금 안내 메일을 다시 보내려는데 받을 수 있는 계좌가 없어요. |
220023 |
409 | 입금 안내 메일을 다시 보내려는데 입금 기한이 없어요. |
입금
code |
HTTP | 설명 |
|---|---|---|
210001 |
422 | 입금 ID 형식이 틀렸어요. |
210002 |
422 | status 필터 값이 목록에 없어요. |
210003 |
422 | matchMethod 필터 값이 목록에 없어요. |
200001 |
422 | bankAccountId 필터에 형식이 틀린 계좌 ID가 있어요. |
현금영수증
code |
HTTP | 설명 |
|---|---|---|
240001 |
422 | 현금영수증 ID 형식이 틀렸어요. |
240002 |
422 | type이 PERSONAL, CORPORATE가 아니거나, CORPORATE로 자진발급하려고 했어요. |
240003 |
422 | identifier가 type에 맞지 않아요. |
240004 |
422 | 금액이 1원부터 999,999,999원 사이가 아니거나, 취소 금액이 남은 금액보다 커요. |
240005 |
409 | 사업자 정보를 등록하지 않았어요. |
240006 |
409 | 취소할 수 없는 현금영수증이에요. data.reason에 이유가 와요. |
240007 |
409 | 재발급할 수 없는 현금영수증이에요. 발급에 실패한 원본만, 한 번만 재발급할 수 있어요. |
240008 |
422 | 팝빌이 재발급이나 취소를 거절했어요. data에 status가 FAILED인 현금영수증이 와요. 발급은 거절돼도 이 코드 대신 HTTP 200과 FAILED 현금영수증이 와요. |
240009 |
502 | 팝빌 호출이 실패했어요. data에 팝빌 오류 코드와 메시지가 와요. |
240010 |
422 | 취소 사유가 비었거나 100자를 넘어요. |
240011 |
422 | status 필터 값이 목록에 없어요. |
240012 |
409 | 이 주문에는 이미 발급했거나 발급 중인 현금영수증이 있어요. data.cashReceiptId에 그 현금영수증 ID가 와요. |
240014 |
422 | customerName이 40자를 넘어요. |
240015 |
422 | kind 필터 값이 목록에 없어요. |
240016 |
422 | method 필터 값이 목록에 없어요. |
240018 |
422 | 이메일 주소 형식이 틀렸어요. |
240020 |
409 | 아직 문서를 열거나 보낼 수 없는 현금영수증이에요. |
서버 오류 (5xx)
code |
HTTP | 설명 |
|---|---|---|
50001 |
500 | 서버에서 오류가 났어요. 잠시 뒤 다시 시도하세요. |
50002 |
502 | 외부 서비스 호출이 실패했어요. 잠시 뒤 다시 시도하세요. |
예상하지 못한 서버 오류는 code 없이 본문이 빈 500으로 올 수 있어요. 응답 본문이 JSON이 아니어도 처리할 수 있게 만들어 주세요.
처리 예시
const res = await fetch(url, options);
const body = await res.json().catch(() => ({ code: null }));
switch (body.code) {
case "10001":
return body.data ?? body.items;
case "290006":
throw new Error("API 키를 확인하세요.");
case "220010":
// 같은 입금자명과 금액의 주문이 이미 있어요.
return { duplicateOf: body.data.invoiceId };
case "220002":
case "220003":
case "220004":
case "220005":
throw new ValidationError(body.code);
default:
if (res.status >= 500) return retryLater();
// 새로 추가된 코드일 수 있어요. 기록하고 일반 오류로 처리하세요.
logger.warn({ code: body.code, status: res.status }, "unknown PaySync code");
throw new Error(`PaySync error: ${body.code}`);
}