Step types
Rundun supports 11 step types. The type field on a step determines the UI control rendered to the executor and the shape of the answer value stored on the run.
Quick reference
| Type | Visual control | Answer shape |
|---|---|---|
boolean |
Checkbox / toggle | true or false |
choice |
Single-select list | "o-fu2" (option ID string) |
multi_choice |
Multi-select list | ["o-dm1", "o-dm3"] (array of option IDs) |
text |
Text input or text area | "Scratch on rear left door" |
number |
Numeric keypad input | 42150 |
rating |
Horizontal scale | 4 (integer) |
photo |
Camera launcher | null (answer is the photos array) |
signature |
Signature pad | "https://media.rundun.app/runs/.../sig.png" |
instruction |
Read-only text block | null (acknowledged) |
barcode |
Camera in scan mode | "VIN1234567890" |
datetime |
Date/time picker | "2026-05-10" or "2026-05-10T14:00:00Z" |
boolean
A single yes/no toggle. Use for binary decisions. Use choice when there are 3 or more options.
{
"id": "s-cl01",
"type": "boolean",
"label": "Is the unit clean and ready for the next guest?",
"hint": "Check all rooms, bathroom, and kitchen",
"required": true,
"photo": false,
"geo": false,
"config": {
"true_label": "Yes, ready",
"false_label": "No, needs attention"
}
}
true_label and false_label are optional. Default to "Yes" / "No".
choice
A single-select list. The answer is the ID of the selected option.
{
"id": "s-fu01",
"type": "choice",
"label": "Fuel level",
"required": true,
"photo": false,
"geo": false,
"config": {
"options": [
{ "id": "o-fu1", "label": "Full" },
{ "id": "o-fu2", "label": "3/4" },
{ "id": "o-fu3", "label": "1/2" },
{ "id": "o-fu4", "label": "1/4" },
{ "id": "o-fu5", "label": "Empty" }
]
}
}
The answer value ("o-fu2") is the option ID, not the label. This means you can rename options without breaking existing answers.
multi_choice
A multi-select list. The answer is an array of selected option IDs.
{
"id": "s-dm02",
"type": "multi_choice",
"label": "Damage types found",
"hint": "Select all that apply",
"required": true,
"photo": { "min": 1, "max": 6, "annotate": false },
"geo": false,
"config": {
"options": [
{ "id": "o-dm1", "label": "Scratch" },
{ "id": "o-dm2", "label": "Dent" },
{ "id": "o-dm3", "label": "Crack" },
{ "id": "o-dm4", "label": "Paint chip" }
]
}
}
Answer example: ["o-dm1", "o-dm3"] — scratch and crack were selected.
text
A freeform text input. Use multiline: true for longer responses.
{
"id": "s-dm03",
"type": "text",
"label": "Describe the damage",
"hint": "Be as specific as possible — include location",
"required": true,
"photo": false,
"geo": false,
"config": {
"multiline": true,
"max_length": 500,
"placeholder": "e.g. Scratch on rear left door, approx 15cm"
}
}
max_length is optional. placeholder is hint text shown inside the input when empty.
number
A numeric input rendered with a numeric keypad on mobile.
{
"id": "s-od01",
"type": "number",
"label": "Odometer reading",
"required": true,
"photo": false,
"geo": false,
"config": {
"unit": "km",
"min": 0,
"max": 999999,
"decimal": 0
}
}
| Config field | Description |
|---|---|
unit |
Label shown after the input (e.g. "km", "$", "%") — optional |
min / max |
Range validation — optional |
decimal |
Number of decimal places allowed. 0 = integers only |
rating
A horizontal tap-to-select scale. The answer is an integer.
{
"id": "s-cl02",
"type": "rating",
"label": "Interior cleanliness",
"required": true,
"photo": { "min": 0, "max": 3 },
"geo": false,
"config": {
"min": 1,
"max": 5,
"low_label": "Very dirty",
"high_label": "Spotless"
}
}
low_label and high_label are optional labels displayed at the ends of the scale.
photo
A camera step where the answer itself is one or more photos. Use this when no other answer type is needed.
For adding photos to any other step type (e.g. take a photo after answering a boolean), use the photo overlay field on the step instead — see Photos.
{
"id": "s-fp01",
"type": "photo",
"label": "Front of vehicle",
"hint": "Take a straight-on shot showing the full front",
"required": true,
"photo": false,
"geo": false,
"config": {
"min": 1,
"max": 3,
"annotate": false
}
}
The answer value in webhook payloads is null for photo steps — the photos are in the photos array.
signature
A signature pad rendered on screen. The executor draws their signature. The result is uploaded to Rundun's servers and the URL is stored as the answer.
{
"id": "s-sg01",
"type": "signature",
"label": "Customer signature",
"hint": "Customer confirms the vehicle condition as documented above",
"required": true,
"photo": false,
"geo": false,
"config": {}
}
Answer: "https://media.rundun.app/runs/r-550e8400-.../s-sg01/sig.png"
instruction
A read-only text block the executor must acknowledge before proceeding. No answer is captured.
Use for safety warnings, procedural notes, or contextual information between steps.
{
"id": "s-in01",
"type": "instruction",
"label": "Walk around the entire vehicle before starting",
"hint": "Check all four sides, the roof, and underneath the bumpers",
"required": false,
"photo": false,
"geo": false,
"config": {}
}
The answer value in webhook payloads is null for instruction steps.
barcode
A camera in scan mode for QR codes and barcodes. The decoded string is stored as the answer.
{
"id": "s-vin1",
"type": "barcode",
"label": "Scan vehicle VIN",
"hint": "Located on the dashboard, visible through the windshield",
"required": true,
"photo": false,
"geo": false,
"config": {
"formats": ["code128", "qr", "code39", "any"]
}
}
formats is optional. Use "any" to accept all supported formats. Supported values: "qr", "code128", "code39", "ean13", "ean8", "datamatrix", "any".
Answer: "JN1AZ4EH2FM123456" (the decoded barcode value).
datetime
A native date and/or time picker.
{
"id": "s-rt01",
"type": "datetime",
"label": "Expected return date",
"required": true,
"photo": false,
"geo": false,
"config": {
"mode": "date",
"min_offset_hours": 1,
"max_offset_days": 30
}
}
| Config field | Description |
|---|---|
mode |
"date" (date only), "time" (time only), or "datetime" (both) |
min_offset_hours |
Minimum selectable time, expressed as hours from now — optional |
max_offset_days |
Maximum selectable date, expressed as days from now — optional |
Answer format:
mode: "date"→"2026-05-22"(ISO 8601 date)mode: "time"→"14:30"(24-hour HH:MM)mode: "datetime"→"2026-05-22T14:30:00Z"(ISO 8601 datetime, UTC)
Photo overlay
Any step type (except photo) can require photos in addition to its primary answer. Set the photo field on the step:
{
"id": "s-dm01",
"type": "boolean",
"label": "Any damage to bodywork?",
"required": true,
"photo": { "min": 0, "max": 4, "annotate": false },
"config": { "true_label": "Yes", "false_label": "No" }
}
min: 0— photos are optionalmin: 1— at least one photo required before the step can be completedmax— maximum photos allowed (1–10)annotate— drawing overlay on photos (post-MVP, alwaysfalsefor now)
photo: false or omitting photo entirely means no camera is shown for that step.
See Photos for the full upload flow and how photos appear in webhook payloads.