Skip to Content
개발자에러 코드

에러 코드

Posmit API의 모든 에러 응답은 RFC 7807  표준을 따르는 application/problem+json 형식으로 반환됩니다. 성공 응답이 data / meta envelope로 감싸지는 것과 달리, 에러 응답은 envelope 없이 problem 객체 하나만 내려갑니다.

응답 구조

{ "type": "https://api.posmit.io/errors/noti-4014", "title": "Unauthorized", "status": 401, "detail": "Invalid HMAC signature", "code": "NOTI-4014", "instance": "/v1/notifications", "timestamp": "2026-07-10T09:00:00.000Z" }
필드타입설명
typestring에러 유형을 식별하는 URI입니다. code 소문자를 붙여 생성되며, 미설정 환경에서는 about:blank입니다.
titlestringHTTP 상태에 대응하는 표준 문구입니다. (Bad Request, Unauthorized 등)
statusnumberHTTP 상태 코드와 동일한 값입니다.
detailstring사람이 읽을 수 있는 상세 원인입니다. 유효성 검증 실패 시 여러 메시지가 ; 로 연결됩니다.
codestring구조화된 에러 코드입니다. 클라이언트 분기는 이 값을 기준으로 하는 것을 권장합니다.
instancestring에러가 발생한 요청 경로입니다.
timestampstring에러 발생 시각(ISO 8601)입니다.

title은 상태 코드별 고정 문구이고 detail은 상황에 따라 달라질 수 있습니다. 프로그램 분기는 statuscode로 처리하고, detail은 로그·디버깅 용도로만 사용하세요.

에러 코드 체계

에러 코드는 NOTI- 접두어 뒤에 HTTP 상태 기반 번호가 붙는 형식입니다.

  • 명시적 코드 — 인증(401 계열)과 요청 한도(429 계열) 에러는 세분화된 4자리 코드를 반환합니다. (예: NOTI-4014)
  • 폴백 코드 — 그 외 에러는 NOTI-<HTTP상태>00 형식의 5자리 폴백 코드를 반환합니다. 예를 들어 400 에러는 NOTI-40000, 403은 NOTI-40300, 404는 NOTI-40400, 500은 NOTI-50000입니다.

422 검증 계열(NOTI-4220), 404 세부 계열(NOTI-4440) 등 일부 코드는 예약만 되어 있고 아직 반환되지 않습니다. 현재 요청 본문 검증 실패는 422가 아니라 HTTP 400 + NOTI-40000 으로 반환됩니다.

주요 에러 코드

401 — 인증 실패

코드발생 조건대응 방법
NOTI-4010API 키가 없거나 비활성 상태, 또는 시크릿 불일치X-API-Key 헤더의 keyId·keySecret을 확인합니다.
NOTI-4011API 키 만료대시보드에서 새 키를 발급합니다.
NOTI-4013인증 헤더 누락X-API-Key, X-Timestamp, X-Nonce, X-Signature 4종이 모두 있는지 확인합니다. detail에 누락된 헤더 이름이 표시됩니다.
NOTI-4014HMAC 서명 불일치canonical string 구성과 raw body 해시를 점검합니다. 서명 후 본문을 재직렬화하면 서명이 깨집니다.
NOTI-4015타임스탬프 허용 오차(기본 ±300초) 초과서버 시계 동기화(NTP)를 확인하고, X-Timestamp초 단위 epoch인지 확인합니다.
NOTI-4016Nonce 재사용(리플레이) 감지요청마다 새로운 X-Nonce 값을 생성합니다.

429 — 요청 한도 초과

코드발생 조건
NOTI-4290워크스페이스 요청 한도 초과
NOTI-4291API 키 요청 한도 초과

자세한 한도 정책과 재시도 전략은 요청 한도 문서를 참고하세요.

폴백 코드로 반환되는 에러

코드HTTP대표 사례
NOTI-40000400요청 본문 검증 실패, 정의되지 않은 필드 포함, 템플릿 없음, scheduledAt 형식 오류 등
NOTI-40300403API 키 스코프 부족, 템플릿 화이트리스트 위반
NOTI-40400404존재하지 않거나 다른 워크스페이스의 requestId 조회
NOTI-50000500서버 내부 오류

Posmit API는 정의되지 않은 필드를 조용히 무시하지 않고 400으로 거부합니다. 요청 스키마에 없는 필드를 보내면 NOTI-40000과 함께 해당 필드명이 detail에 표시됩니다.

자주 만나는 detail 메시지

detail은 변경될 수 있으므로 분기 조건으로 쓰지 말고, 원인 파악 참고용으로만 사용하세요.

HTTPdetail원인
400content.text is required when templateCode is missing템플릿 없이 발송할 때 content.text 누락
400Template not found or disabled: {code}존재하지 않거나 비활성화된 템플릿 코드
400Published template version missing: {code}게시(published)된 템플릿 버전 없음
400Alimtalk template is not approved (status=...): {code}검수 승인되지 않은 알림톡 템플릿
400scheduledAt must be a valid ISO-8601 datetime예약 시각 형식 오류
400scheduledAt must be in the future예약 시각이 현재 또는 과거
400Validation failed (uuid is expected)requestId 경로 파라미터가 UUID 형식이 아님
403API key missing required scope: {scope}API 키에 필요한 스코프 없음
403API key is not allowed to send template: {code}API 키 템플릿 화이트리스트 위반
404Notification request not found요청 미존재 또는 다른 워크스페이스 소속

처리 가이드

에러 처리는 다음 순서를 권장합니다.

  1. HTTP 상태 코드로 큰 분기를 나눕니다. (4xx는 요청 수정, 5xx·429는 재시도)
  2. 401·429처럼 세분화가 필요한 경우 code 로 추가 분기합니다.
  3. detail·instance·timestamp는 로그에 남겨 디버깅에 활용합니다.
type ProblemDetails = { type: string title: string status: number detail: string code: string instance: string timestamp: string } const res = await fetch('https://api.posmit.io/v1/notifications', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'YOUR_KEY_ID.YOUR_KEY_SECRET', 'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature, }, body, }) if (!res.ok) { const problem = (await res.json()) as ProblemDetails switch (problem.code) { case 'NOTI-4015': // 서버 시계 오차 — NTP 동기화 확인 후 재서명하여 재시도 break case 'NOTI-4016': // Nonce 재사용 — 새 nonce로 재서명하여 재시도 break case 'NOTI-4290': case 'NOTI-4291': // 요청 한도 초과 — 윈도우가 지난 뒤 재시도 break default: if (problem.status >= 500) { // 일시 장애 — 지수 백오프로 재시도 } else { // 요청 자체의 문제 — 재시도하지 말고 요청을 수정 console.error(`[${problem.code}] ${problem.detail}`) } } }

4xx 에러(429 제외)는 같은 요청을 다시 보내도 같은 결과가 반환됩니다. 자동 재시도 대상에서 제외하세요. 재시도는 429와 5xx에만 적용하고, 발송 요청 재시도 시에는 idempotencyKey를 함께 사용해 중복 발송을 방지하는 것을 권장합니다.

발송 실패와의 구분

이 문서의 에러는 API 요청 자체가 거부된 경우입니다. 요청이 정상 접수(201)된 뒤 공급자 발송 단계에서 실패하는 경우는 HTTP 에러가 아니라, 요청 상태가 failed로 바뀌고 finalErrorCode에 실패 코드가 기록됩니다. 발송 단계의 실패 코드와 폴백 동작은 라우팅과 폴백을 참고하세요.

Last updated on