Forms
Publish reusable form templates that recipients fill in from their inbox, then read the responses back. Covers field types, template lifecycle, and collecting responses.
A form is a structured question set a recipient fills in from their inbox: an address change, a survey, a KYC update. You define a template once, deliver it, and read responses back as they come in. Forms are how you collect structured data from recipients, the inverse of sending content to them.
Templates and responses need forms.write to create and delete, forms.read to
read.
Define a template
A template has a title, an optional description, and an ordered list of
fields. Each field has a stable field_id (the key answers come back under), a
label, a type, and whether it is required:
curl https://api.keepable.co/tenants/ten_01HXP/forms \
-H "Authorization: Bearer $KEEPABLE_TOKEN" \
-H "Keepable-Version: 2026-05-24" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"title": "Address change",
"description": "Tell us where to reach you.",
"fields": [
{ "field_id": "street", "label": "Street", "type": "text", "required": true },
{ "field_id": "state", "label": "State", "type": "choice", "required": true,
"options": ["Lagos", "Abuja", "Rivers", "Kano"] }
]
}'const res = await fetch(
"https://api.keepable.co/tenants/ten_01HXP/forms",
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Keepable-Version": "2026-05-24",
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Address change",
description: "Tell us where to reach you.",
fields: [
{ field_id: "street", label: "Street", type: "text", required: true },
{ field_id: "state", label: "State", type: "choice", required: true,
options: ["Lagos", "Abuja", "Rivers", "Kano"] },
],
}),
},
);
const { form_id } = await res.json();{
"form_id": "frm_01HXP",
"title": "Address change",
"fields": [
{ "field_id": "street", "label": "Street", "type": "text", "required": true }
]
}Field types
type | Collects | Notes |
|---|---|---|
text | A free-text string | |
number | A numeric value | |
date | A calendar date | |
rating | A rating value | Pairs well with survey content. |
choice | One of a fixed set | Supply the set in options. |
Give field_id a stable, meaningful slug (street, not field_1): it is the
key you read answers under, so a good id makes response handling self-documenting.
Deliver the form
Templates are delivered to recipients as content with the form
content type. The recipient fills it
in from their inbox, and you read the submitted responses back here.
Read responses
List the responses to a template (paginated). Each summary carries the
response_id, when it was submitted_at, and which recipient_id submitted it:
curl "https://api.keepable.co/tenants/ten_01HXP/forms/frm_01HXP/responses?limit=50" \
-H "Authorization: Bearer $KEEPABLE_TOKEN" \
-H "Keepable-Version: 2026-05-24"{
"responses": [
{ "response_id": "rsp_01HXP", "submitted_at": "2026-05-24T12:00:00Z", "recipient_id": "rcp_01HXP" }
],
"next_token": null
}Fetch a single response to get the answers, keyed by your field_ids:
curl https://api.keepable.co/tenants/ten_01HXP/forms/frm_01HXP/responses/rsp_01HXP \
-H "Authorization: Bearer $KEEPABLE_TOKEN" \
-H "Keepable-Version: 2026-05-24"{
"response_id": "rsp_01HXP",
"form_id": "frm_01HXP",
"submitted_at": "2026-05-24T12:00:00Z",
"recipient_id": "rcp_01HXP",
"answers": { "street": "12 Marina Rd", "state": "Lagos" }
}Manage templates and responses
| Operation | Endpoint |
|---|---|
| List templates | GET /tenants/{tenant_id}/forms |
| Fetch a template | GET /tenants/{tenant_id}/forms/{form_id} |
| Delete a template | DELETE /tenants/{tenant_id}/forms/{form_id} |
| List responses | GET /tenants/{tenant_id}/forms/{form_id}/responses |
| Fetch a response | GET /tenants/{tenant_id}/forms/{form_id}/responses/{response_id} |
| Delete a response | DELETE /tenants/{tenant_id}/forms/{form_id}/responses/{response_id} |
Deleting a template does not retract forms already delivered to inboxes, and deleting a response is permanent: there is no trash for form data. Delete a response only when a data-retention or correction obligation requires it.
Agreements
Run e-signature workflows. Send a document to one or more signers, track signatures as they land, and download a tamper-evident PAdES-LTV covenant when everyone has signed.
Tenants
A tenant is your organisation inside Keepable, the entity that owns content, agreements, forms, and branding. Create and manage tenants, attach TINs, and set the icon recipients see.