REST API
시크릿 키로 폼과 제출을 읽고, 제출을 스팸으로 옮기거나 되돌리고, 삭제하세요.
REST API로 서버에서 폼과 제출을 읽고, 제출을 스팸으로 옮기거나 되돌리고, 삭제할 수 있습니다. https://ikiform.com/api/v1에서 HTTPS로 JSON을 주고받습니다. OpenAPI 3.1 문서는 /api/v1/openapi.json에 있습니다.
/api/v1에 포함되지 않습니다. 대신 시크릿 키와 함께 폼 엔드포인트로 POST하세요. 서버에서 보내기를 참고하세요.API 키
대시보드의 API keys에서 키를 만드세요. 키는 하나의 워크스페이스에 속하며 그 워크스페이스만 볼 수 있습니다. 전체 키는 한 번만 표시되며, Ikiform은 해시만 저장합니다.
| 종류 | 접두사 | 용도 |
|---|---|---|
| 시크릿 | ik_sk_ | 서버용. 선택한 스코프로 REST API를 호출하고, 제출을 생성할 수 있습니다. |
| 퍼블리셔블 | ik_pub_ | 브라우저용. 폼 제출만 할 수 있고, 키에 등록한 도메인에서만 작동합니다. |
스코프
| 스코프 | 허용 범위 |
|---|---|
forms:read | GET /forms, GET /forms/:formId |
submissions:read | GET /submissions, GET /submissions/:id |
submissions:write | DELETE /submissions/:id, POST /submissions/:id/spam과 /not-spam, 그리고 /f/:formId로 POST |
인증
시크릿 키를 Bearer 토큰으로 보내세요. 이 API는 서버 간 통신 전용입니다. CORS 헤더를 보내지 않고 브라우저 프리플라이트에 405로 응답하므로, 시크릿 키는 웹 페이지에서 절대 작동하지 않습니다.
curl https://ikiform.com/api/v1/forms \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"- 키가 없거나, 형식이 잘못되었거나, 알 수 없거나, 폐기되었거나, 만료되었으면
WWW-Authenticate: Bearer와 함께401 unauthorized를 받습니다. - 퍼블리셔블 키는
403 forbidden(Publishable keys can only submit forms.)을 받습니다. 필요한 스코프가 없는 키는 메시지에 해당 스코프가 적힌403 forbidden을 받습니다. - 응답은
Cache-Control: no-store와 함께 전송됩니다.
아래 SDK 예제는 모두 하나의 클라이언트를 공유합니다.
import { createClient } from "@ikiform/sdk";
const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY! });요청 작성기
curl "https://ikiform.com/api/v1/submissions?form_id=frm_xxxxxxxxxxxxxxxx&status=received&limit=50" \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"서버에서 실행하세요. REST API는 브라우저 요청을 거부하므로 이 페이지에서는 보내지 않습니다.
엔드포인트
| 메서드 | 경로 | 스코프 | 반환 |
|---|---|---|---|
GET | /forms | forms:read | 폼 목록 |
GET | /forms/:formId | forms:read | 폼 조회 |
GET | /submissions | submissions:read | 제출 목록 |
GET | /submissions/:id | submissions:read | 제출 조회 |
POST | /submissions/:id/spam | submissions:write | 스팸으로 표시 |
POST | /submissions/:id/not-spam | submissions:write | 스팸 아님으로 표시 |
DELETE | /submissions/:id | submissions:write | 제출 삭제 |
GET | /openapi.json | 없음 | OpenAPI 문서 |
GET | /health | 없음 | { "ok": true } |
폼 목록
forms:read 스코프로 GET /forms.
- 최신순입니다.
limit(1~100, 기본값 25)과cursor를 받습니다.
curl "https://ikiform.com/api/v1/forms?limit=10" \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"폼 조회
forms:read 스코프로 GET /forms/:formId.
- 다른 워크스페이스의 폼 ID는 존재하지 않는 ID와 똑같이
404를 반환합니다.
curl https://ikiform.com/api/v1/forms/frm_xxxxxxxxxxxxxxxx \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"제출 목록
submissions:read 스코프로 GET /submissions.
| 파라미터 | 값 | 기본값 |
|---|---|---|
form_id | 폼 ID | 워크스페이스의 모든 폼 |
status | received 또는 spam | 둘 다 |
limit | 1~100 | 25 |
cursor | 이전 페이지의 next_cursor | 첫 페이지 |
- 최신순입니다. 다른 워크스페이스의
form_id는 오류 대신 빈 목록을 반환하므로 ID를 탐색할 수 없습니다.
curl "https://ikiform.com/api/v1/submissions?form_id=frm_xxxxxxxxxxxxxxxx&status=received&limit=50" \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"제출 조회
submissions:read 스코프로 GET /submissions/:id.
- 다른 워크스페이스의 ID는 존재하지 않는 ID와 똑같이
404를 반환합니다.
curl https://ikiform.com/api/v1/submissions/sub_01k7v2c9t3e8m5q4x6z0a1b2c3 \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"스팸으로 표시
submissions:write 스코프로 POST /submissions/:id/spam.
- 수신된 제출을 스팸으로 옮기고, 폼의
submission_count를 줄이고, 대기 중인 웹훅 전송을 취소합니다. - 이미 스팸인 제출에 호출하면 변경 없이 그대로 반환합니다.
curl -X POST https://ikiform.com/api/v1/submissions/sub_01k7v2c9t3e8m5q4x6z0a1b2c3/spam \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"스팸 아님으로 표시
submissions:write 스코프로 POST /submissions/:id/not-spam.
- 제출을 다시 수신 상태로 옮기고, 스팸 점수와 사유를 지우고, 일치하는 모든 웹훅 엔드포인트로
submission.created를 보냅니다. - 수신 상태인 제출에 호출하면 변경 없이 그대로 반환합니다.
curl -X POST https://ikiform.com/api/v1/submissions/sub_01k7v2c9t3e8m5q4x6z0a1b2c3/not-spam \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"제출 삭제
submissions:write 스코프로 DELETE /submissions/:id.
- 제출과 그 웹훅 전송을 영구적으로 삭제합니다. 되돌릴 수 없습니다. 다시 삭제하면
404를 반환합니다.
curl -X DELETE https://ikiform.com/api/v1/submissions/sub_01k7v2c9t3e8m5q4x6z0a1b2c3 \
-H "Authorization: Bearer $IKIFORM_SECRET_KEY"객체
객체는 object 필드가 있는 snake_case JSON입니다. 타임스탬프는 밀리초를 포함한 UTC 기준 ISO 8601입니다. 제출 ID는 시간순으로 정렬되며(sub_ 뒤에 26자), 폼 ID는 무작위입니다(frm_ 뒤에 16자).
| 폼 필드 | 설명 |
|---|---|
status | active, paused 또는 disabled |
submission_count | 스팸을 제외한 수신 제출 수 |
| 제출 필드 | 설명 |
|---|---|
status | received 또는 spam |
fields | 저장된 값 |
meta | user_agent, origin, referrer, country, subject, reply_to. 모든 키가 항상 있으며 어떤 값이든 null일 수 있습니다. IP 해시는 절대 반환하지 않습니다 |
spam.score, spam.reasons | 스팸 점수와 honeypot, origin_mismatch 같은 사유 |
페이지네이션
목록은 최신순이며 불투명 커서를 사용합니다.
- 커서 없이 요청합니다.
has_more가 true이면 같은 필터와 함께next_cursor를cursor로 보냅니다.next_cursor가null이면 멈춥니다.
새 제출이 들어와도 페이지는 안정적으로 유지됩니다. 새 제출은 첫 페이지에 나타나며, 뒤쪽 페이지에 중복으로 나타나지 않습니다. 커서를 직접 만들거나 파싱하지 마세요. 잘못된 커서는 400 invalid_request를 반환합니다.
for await (const submission of ikiform.submissions.iterate({ formId: "frm_xxxxxxxxxxxxxxxx" })) {
console.log(submission.id, submission.fields);
}오류
오류는 폼 제출과 같은 형식을 사용합니다. 모든 응답에는 X-Request-Id 헤더가 있으며, 오류에는 이 값이 request_id로도 담깁니다.
{
"ok": false,
"error": { "code": "forbidden", "message": "This API key is missing the forms:read scope." },
"request_id": "req_01k7v2c9t3e8m5q4x6z0a1b2c3"
}| 상태 | 코드 | 발생 조건 |
|---|---|---|
| 400 | invalid_request | limit, status, form_id, cursor 중 하나가 잘못됨. 메시지에 해당 항목이 표시됩니다 |
| 401 | unauthorized | 키가 없거나 잘못됨 |
| 403 | forbidden | 퍼블리셔블 키 또는 스코프 누락 |
| 404 | not_found | 알 수 없는 경로나 ID, 또는 다른 워크스페이스의 ID |
| 405 | method_not_allowed | 브라우저 프리플라이트 |
| 429 | rate_limited | 키별 레이트 리밋 초과 |
| 500 | server_error | Ikiform 쪽에서 문제가 발생함. request_id를 알려 주세요 |
레이트 리밋
키마다 60초에 100건의 요청을 보낼 수 있습니다. 한도를 넘으면 API는 초 단위의 Retry-After 헤더와 함께 429 rate_limited를 반환합니다. SDK에서는 error.retryAfter로 제공됩니다.