Intake Forms API¶
Intake forms are public or internal web forms that create issues when submitted. Standalone products use them for customer-facing submissions (GDPR requests, support tickets, contract requests).
Public Submission (No Auth Required)¶
Submit to a form using its slug. No authentication needed for public forms.
Embed endpoint (JSON)¶
POST https://kiket.dev/intake/{slug}/embed
Content-Type: application/json
{
"intake_submission": {
"data": {
"title": "GDPR Data Access Request",
"request_type": "access",
"requester_email": "jan@example.com",
"description": "I would like a copy of all personal data you hold about me."
}
}
}
Response:
{
"success": true,
"message": "Thank you for your submission!",
"submission_id": "a1b2c3d4-...",
"redirect_url": "https://spravce-gdpr.cz/thank-you"
}
Error response (422):
Organization-scoped submission¶
Prefill fields via URL¶
Query parameters matching prefill_{field_key} pre-populate form fields.
Rate limiting¶
Public forms enforce per-IP rate limits (configurable per form, default from plan). Returns 429 Too Many Requests when exceeded.
CAPTCHA¶
Public forms can require Cloudflare Turnstile verification. Pass the token as cf-turnstile-response in the submission.
CORS for embeds¶
Forms support cross-origin embedding. Configure allowed_origins on the intake form (supports wildcards: https://*.example.com). The embed endpoint sets appropriate CORS headers and X-Frame-Options: ALLOWALL.
Authenticated API¶
Requires Authorization: Bearer <token>.
List forms¶
Response:
{
"intake_forms": [
{
"id": "uuid",
"key": "gdpr-request",
"slug": "gdpr-request",
"name": "GDPR Data Subject Request",
"description": "Public form for GDPR data subject requests",
"active": true,
"public": true,
"requires_approval": true,
"default_issue_type": "dsar",
"default_priority": "high",
"form_url": "https://kiket.dev/intake/gdpr-request",
"created_at": "2026-04-01T00:00:00Z"
}
]
}
Show form with fields¶
Returns the form configuration including all field definitions (types, labels, options, validation rules, mapping).
List submissions¶
GET /api/v1/projects/{project_id}/intake_forms/{form_id}/submissions
# Filters
?status=pending # pending, approved, rejected, converted
?since=2026-01-01T00:00:00Z
?until=2026-12-31T23:59:59Z
?page=1&per_page=25 # max 100
Response:
{
"submissions": [
{
"id": "uuid",
"status": "pending",
"submitter_name": "Jan Novak",
"submitter_email": "jan@example.com",
"submitted_at": "2026-04-01T12:00:00Z",
"issue_id": null,
"notes": null
}
],
"meta": {
"current_page": 1,
"total_pages": 5,
"total_count": 123
}
}
Show submission¶
Response includes full data (field values), attachments (with download URLs), and linked issue if converted.
{
"submission": {
"id": "uuid",
"status": "converted",
"data": {
"title": "GDPR Data Access Request",
"request_type": "access",
"requester_email": "jan@example.com",
"description": "..."
},
"attachments": [
{
"id": "uuid",
"filename": "id-verification.pdf",
"content_type": "application/pdf",
"byte_size": 45000,
"url": "https://..."
}
],
"issue": {
"id": 456,
"key": "GDPR-42",
"title": "GDPR Data Access Request",
"status": "open"
},
"submitted_at": "2026-04-01T12:00:00Z",
"processed_at": "2026-04-01T14:30:00Z"
}
}
Create submission via API¶
POST /api/v1/projects/{project_id}/intake_forms/{form_id}/submissions
{
"submission": {
"data": {
"title": "Feature request",
"description": "Add dark mode support"
}
}
}
No authentication required for public forms.
Processing Pipeline¶
- Submit — Form data validated against field definitions
- Rate limit — Per-IP, per-form, per-hour check
- CAPTCHA — Turnstile verification (if enabled)
- Save —
IntakeSubmissioncreated withstatus: pending - Process — If
requires_approval: false, automatically converts to issue: - Maps fields to issue attributes (
title,description,priority,assignee,custom_fields) - Creates issue in the project with configured workflow
- Updates submission
status: convertedwithissue_id - If
requires_approval: true— Stays aspendinguntil admin approves via UI
Submission Statuses¶
| Status | Description |
|---|---|
pending |
Awaiting review (when requires_approval: true) |
approved |
Approved by admin, converted to issue |
rejected |
Rejected by admin (with optional notes) |
converted |
Automatically converted to issue |