오류
모든 오류 응답은 Resend와 동일한 같은 JSON 형식을 가집니다.
{ "statusCode": 422, "name": "validation_error", "message": "`from`: Invalid email address"}변하지 않는 name으로 분기하세요. message는 사람이 읽기 위한 것이며 바뀔 수 있습니다. Node SDK에서는 오류가 같은 세 필드를 가진 { data: null, error }로 반환되며, 네트워크 실패는 name: "application_error"와 statusCode: null을 사용합니다.
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost();
const { data, error } = await spacepost.emails.send({ from: "Acme <hello@acme.com>", to: "user@example.com", subject: "Hello", html: "<p>Hello</p>",});
if (error) { switch (error.name) { case "rate_limit_exceeded": // wait about a second, then retry with the same idempotency key break; case "daily_quota_exceeded": case "monthly_quota_exceeded": // alert someone: you hit a limit break; case "validation_error": case "invalid_from_address": // a bug in your request: do not retry throw new Error(`${error.name}: ${error.message}`); default: console.error(error.statusCode, error.name, error.message); }} else { console.log(data.id);}오류 표
섹션 제목: “오류 표”| 상태 | name |
의미와 해결 방법 |
|---|---|---|
| 400 | invalid_idempotency_key |
Idempotency-Key 헤더가 1자 이상 256자 이하가 아닙니다. |
| 401 | missing_api_key |
Authorization: Bearer sp_live_... 헤더가 없습니다. |
| 401 | restricted_api_key |
이 키로는 할 수 없는 작업입니다. 발송용이 아닌 엔드포인트에 sending_access 키를 썼거나, 도메인으로 제한된 키로 다른 도메인에서 발송했습니다. |
| 403 | invalid_api_key |
키를 알 수 없거나, 폐기되었거나, SpacePost 키가 아닙니다(예: Resend의 re_ 키). |
| 403 | invalid_from_address |
from 도메인이 팀에서 확인된 도메인이 아닙니다. |
| 403 | sending_paused |
팀이 일시 중지되었습니다. 보통 반송률이나 스팸 신고율이 높을 때이며, tenant_id를 전달했거나 테넌트 소유 도메인에서 발송한 경우에는 해당 테넌트가 일시 중지된 것입니다. 자동 일시 중지를 참고하세요. |
| 403 | validation_error |
유효하지만 허용되지 않는 요청입니다. test.spacepost.dev로 팀이나 테스트 주소가 아닌 수신자에게 메일을 보내거나, 요금제의 도메인 한도를 초과한 경우입니다. |
| 403 | invalid_access |
요청한 팀에 접근할 수 없는 대시보드 세션이거나, trusted가 아닌 팀이 반송률이나 스팸 신고율 때문에 일시 중지된 테넌트에 POST /tenants/{ref}/unpause를 호출한 경우입니다. 지원팀에 문의하세요. |
| 404 | not_found |
리소스가 없거나(또는 다른 팀에 속하거나) 엔드포인트가 없습니다. |
| 405 | method_not_allowed |
이 경로에서 지원하지 않는 HTTP 메서드입니다. |
| 409 | concurrent_idempotent_requests |
같은 멱등성 키가 아직 처리 중입니다. 잠시 후 다시 시도하세요. |
| 409 | invalid_idempotent_request |
멱등성 키가 이미 다른 요청 본문과 함께 사용되었습니다. |
| 422 | validation_error |
필드가 없거나 유효하지 않습니다. 메시지에 해당 필드가 표시됩니다. 그 밖에: “Only scheduled emails can be canceled”, “Domain already registered”, 잘못된 JSON, 도메인의 테넌트와 충돌하는 tenant_id, 중복된 테넌트 external_id, 도메인이 남아 있는 테넌트 삭제. |
| 422 | invalid_parameter |
쿼리 또는 경로 매개변수가 유효하지 않습니다. |
| 429 | rate_limit_exceeded |
초당 요청 한도를 초과했습니다. retry-after 초만큼 기다리세요. |
| 429 | daily_quota_exceeded |
일일 발송 한도에 도달했습니다(신규 계정 샌드박스, 신뢰 등급 상한, 또는 테넌트의 daily_limit). |
| 429 | monthly_quota_exceeded |
Free 플랜의 월 한도에 도달했습니다. 업그레이드하거나 기다리세요. |
| 451 | security_error |
이메일이 콘텐츠 필터링에 차단되었습니다(실행 파일 첨부, 피싱 또는 스팸 징후). 콘텐츠를 바꾸고 그대로 재시도하지 마세요. |
| 500 | application_error |
API에서 예기치 않은 오류가 발생했습니다. 백오프를 적용해 재시도하세요. |
| 500 | internal_server_error |
“An unexpected error occurred, please try again later”. 백오프를 적용해 재시도하고, 계속되면 지원팀에 문의하세요. |
재시도
섹션 제목: “재시도”| 재시도? | 오류 |
|---|---|
예, retry-after 초 이후 |
rate_limit_exceeded |
예, 지수 백오프와 같은 Idempotency-Key로 |
500번대, 네트워크 오류, concurrent_idempotent_requests |
| 아니요, 요청을 고치세요 | 400, 401, 403, 404, 422 |
| 아니요, 한도가 초기화될 때까지 기다리거나 업그레이드하세요 | daily_quota_exceeded, monthly_quota_exceeded |
| 아니요, 지원팀에 문의하세요(또는 직접 일시 중지한 테넌트를 재개하세요) | sending_paused, security_error |
웹훅과 비동기 실패
섹션 제목: “웹훅과 비동기 실패”위의 오류는 요청을 보낼 때 반환됩니다. 이메일이 접수된 뒤에 발생하는 문제(반송, 거부)는 웹훅 이벤트와 이메일의 last_event로 전달됩니다.
SMTP에서는 같은 상황이 SMTP 응답 코드로 반환됩니다. 할당량 오류는 452, 요청 제한은 421, 유효하지 않은 발신자는 553, 그 밖의 거부는 550, 일시적 오류는 451입니다.