오류
Ikiform이 반환하는 모든 오류 코드와 HTTP 상태, 원인, 해결 방법.
폼 제출과 REST API는 같은 오류 형식을 사용합니다. JSON 요청은 해당 HTTP 상태와 함께 이 형식을 받고, 브라우저 폼 POST는 같은 메시지와 상태가 담긴 호스팅 오류 페이지를 받습니다.
오류 형식
{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Too many requests. Please slow down."
},
"request_id": "req_01k7v2c9t3e8m5q4x6z0a1b2c3"
}error.code는 바뀌지 않으므로 분기 처리에 사용하세요.error.message는 사람이 읽는 평이한 영어 문장이며 바뀔 수 있습니다.error.fields는 검증 오류에 포함되며, 필드 ID를 키로 메시지 목록을 담습니다. 본문 전체에 대한 오류는_form키를 사용합니다.error.challenge_url은challenge_required에 포함됩니다.request_id는 모든 응답에 붙는X-Request-Id헤더와 같습니다.- 레이트 리밋 응답에는 초 단위의
Retry-After가 붙습니다. 두 헤더 모두 브라우저 코드에서 읽을 수 있습니다.
코드
| 상태 | 코드 | 발생 위치 |
|---|---|---|
| 400 | invalid_body | 제출 |
| 400 | invalid_request | API |
| 401 | unauthorized | API |
| 402 | plan_required | 제출 |
| 403 | forbidden | 둘 다 |
| 403 | origin_not_allowed | 제출 |
| 403 | form_paused | 제출 |
| 403 | captcha_failed | 제출 |
| 403 | challenge_required | 제출 |
| 404 | not_found | 둘 다 |
| 405 | method_not_allowed | API |
| 409 | idempotency_in_progress | 제출 |
| 413 | payload_too_large | 제출 |
| 415 | unsupported_media_type | 제출 |
| 415 | unsupported_charset | 제출 |
| 422 | validation_failed | 제출 |
| 422 | files_not_supported | 제출 |
| 422 | too_deep | 제출 |
| 422 | idempotency_mismatch | 제출 |
| 429 | rate_limited | 둘 다 |
| 429 | quota_exceeded | 제출 |
| 500 | server_error | 둘 다 |
400 invalid_body
| 메시지 | The request body could not be read. |
| 원인 | 형식이 잘못된 JSON이나 multipart, 객체 대신 JSON 배열이나 문자열, 또는 255자를 넘는 멱등성 키. |
| 해결 | JSON 객체 하나를 보내거나, 브라우저나 FormData가 본문을 만들게 하세요. |
400 invalid_request
| 메시지 | The request is invalid. |
| 원인 | limit, status, form_id, cursor 중 하나가 잘못되었습니다. 메시지에 해당 파라미터가 표시됩니다. |
| 해결 | limit은 1~100, status는 received 또는 spam, 실제 frm_ ID를 사용하고, 커서는 반환된 그대로 사용하세요. |
401 unauthorized
| 메시지 | A valid API key is required. |
| 원인 | Authorization 헤더가 없거나, Bearer 토큰이 아니거나, 알 수 없거나 폐기되었거나 만료된 키입니다. |
| 해결 | 유효한 시크릿 키로 Authorization: Bearer ik_sk_...를 보내세요. |
402 plan_required
| 메시지 | This form isn't accepting submissions right now. |
| 원인 | 워크스페이스에 활성 플랜이 없습니다. 결제 기능이 켜진 뒤에만 발생할 수 있습니다. |
| 해결 | 대시보드의 Settings에서 플랜을 고르세요. |
403 forbidden
| 메시지 | You do not have access to this resource. |
| 원인 | API 키의 형식이 잘못되었거나, 다른 워크스페이스의 키이거나, REST API에 퍼블리셔블 키를 썼거나, 필요한 스코프가 없습니다. |
| 해결 | 이 워크스페이스의 시크릿 키를 메시지에 적힌 스코프와 함께 사용하세요. |
403 origin_not_allowed
| 메시지 | This form does not accept submissions from this site. |
| 원인 | 폼의 허용 도메인 밖의 사이트에서 POST가 왔고 폼이 불일치를 거부하도록 설정되어 있거나, 키에 등록되지 않은 도메인에서 퍼블리셔블 키를 사용했습니다. |
| 해결 | 사이트를 Allowed domains나 키의 도메인에 추가하세요. 서버에서 POST할 때는 시크릿 키를 사용하세요. |
403 form_paused
| 메시지 | This form is not accepting submissions right now. |
| 원인 | 대시보드에서 폼이 일시 중지되어 있습니다. |
| 해결 | 폼을 다시 시작하세요. |
403 captcha_failed
| 메시지 | The captcha check failed. Please try again. |
| 원인 | Turnstile 토큰이 없거나, 만료되었거나, 이미 사용되었거나, 검증되지 않았습니다. |
| 해결 | 제출할 때마다 새 토큰을 받으세요. 직접 발급한 키를 쓴다면 사이트 키와 시크릿이 짝이 맞는지 확인하세요. |
403 challenge_required
| 메시지 | Complete the human check, then send the form again. |
| 원인 | 폼이 Ikiform 사람 확인을 사용하는데 토큰 없이 JSON POST가 도착했습니다. |
| 해결 | SDK의 challenge(formId)를 호출해 토큰을 전달하거나 error.challenge_url을 사용하세요. 서버 POST는 대신 시크릿 키를 보낼 수 있습니다. |
404 not_found
| 메시지 | Not found. |
| 원인 | 폼이 존재하지 않거나, 삭제 또는 비활성화되었거나, ID나 경로가 잘못되었습니다. /f/<formId>로 GET 요청을 보내도 반환됩니다. |
| 해결 | 폼 개요에서 엔드포인트를 복사하고, 탭에서 여는 대신 POST하세요. |
405 method_not_allowed
| 메시지 | This method is not allowed here. |
| 원인 | 서버 간 통신 전용인 REST API에 대한 브라우저 프리플라이트입니다. |
| 해결 | 백엔드에서 /api/v1을 호출하세요. |
409 idempotency_in_progress
| 메시지 | A request with this idempotency key is still being processed. |
| 원인 | 이 멱등성 키를 쓴 요청이 아직 처리 중입니다. |
| 해결 | 잠시 기다린 뒤 같은 키로 다시 시도하면 첫 응답을 받습니다. |
413 payload_too_large
| 메시지 | The submission is too large. |
| 원인 | 본문, 필드 이름, 값, 필드 수 중 하나가 한도를 넘었습니다. 메시지에 어느 것인지 표시됩니다. |
| 해결 | 한도를 참고하세요. 긴 텍스트는 여러 필드로 나누거나, 파일은 다른 곳에 저장하고 링크를 보내세요. |
415 unsupported_media_type
| 메시지 | Send the form as urlencoded, multipart or JSON. |
| 원인 | Content-Type이 urlencoded, multipart, JSON이 아니거나 없습니다. |
| 해결 | JSON을 POST할 때는 Content-Type: application/json을 설정하세요. |
415 unsupported_charset
| 메시지 | Only UTF-8 is supported. |
| 원인 | 본문이 UTF-8이 아니거나 다른 문자 집합을 선언했습니다. |
| 해결 | UTF-8로 인코딩하세요. 오래된 HTML 폼에는 accept-charset="utf-8"을 추가하세요. |
422 validation_failed
| 메시지 | Some fields are invalid. |
| 원인 | 필드가 검증에 실패했습니다. error.fields가 필드 ID와 메시지를 연결합니다. |
| 해결 | 메시지를 필드 옆에 보여 주세요. 필드를 참고하세요. |
422 files_not_supported
| 메시지 | File uploads are not supported yet. |
| 원인 | POST에 파일이 포함되어 있습니다. 파일 업로드는 아직 지원하지 않습니다. |
| 해결 | 파일 입력을 제거하거나, 파일을 다른 곳에 업로드하고 링크를 제출하세요. |
422 too_deep
| 메시지 | The JSON body is nested too deeply. |
| 원인 | JSON 본문이 최상위 객체를 포함해 3단계보다 깊게 중첩되어 있습니다. |
| 해결 | { "address_city": "London" }처럼 데이터를 평평하게 만드세요. |
422 idempotency_mismatch
| 메시지 | This idempotency key was already used with a different payload. |
| 원인 | 이 멱등성 키가 최근 24시간 안에 이 폼에서 다른 필드와 함께 이미 사용되었습니다. |
| 해결 | 새 데이터에는 새 키를 사용하세요. 같은 키는 완전히 같은 재시도에만 쓰세요. |
429 rate_limited
| 메시지 | Too many requests. Please slow down. |
| 원인 | 레이트 리밋을 넘었습니다. Retry-After가 기다려야 할 초를 알려 줍니다. |
| 해결 | 기다린 뒤 다시 시도하세요. 실제 방문자가 한도에 닿는다면 폼의 레이트 리밋을 바꾸세요. |
429 quota_exceeded
| 메시지 | This form isn't accepting submissions right now. |
| 원인 | 워크스페이스가 이번 달에 월간 제출 한도의 2배를 받았습니다. |
| 해결 | 업그레이드하거나 다음 달을 기다리세요. 월간 사용량을 참고하세요. |
500 server_error
| 메시지 | Something went wrong on our side. |
| 원인 | Ikiform 쪽에서 문제가 발생했습니다. |
| 해결 | 백오프와 멱등성 키를 사용해 다시 시도하세요. 계속 발생하면 request_id를 알려 주세요. |
오류가 아닌 경우
- 스팸은 실제 제출과 같은
201이나 리디렉션을 받습니다. 대시보드의 스팸 필터에서 확인하세요. - 허용되지 않은
_redirect는 무시되며, 브라우저는 호스팅 감사 페이지로 이동합니다. - 올바른 이메일 주소 하나가 아닌
_replyto는 무시됩니다.
재시도
429는Retry-After후에,500,409, 네트워크 오류는 백오프로 재시도하세요. 멱등성 키를 보내면 재시도해도 중복이 생기지 않습니다.- 다른
4xx오류는 그대로 재시도하지 마세요. 먼저 요청을 고치세요.