REST API Reference

All API endpoints use the base path /api/v1 and require Bearer token authentication.

Authentication

Include your API key in every request as a Bearer token:

HTTP Header
Authorization: Bearer af_live_your_api_key_here

API keys follow the format af_live_<48 hex chars>. The key is shown once at server startup. It is stored as a SHA-256 hash — the plaintext is never persisted.

Keep your key secret. Do not commit it to source control or expose it in client-side code.

Create Form

POST /api/v1/forms

Create a new form with one or more fields. Returns the form metadata including a public URL for sharing.

Request Body

FieldTypeRequiredDescription
titlestringYesForm title (max 255 chars)
descriptionstringNoOptional description shown on the form
fieldsarrayYesArray of field objects
callback_urlstringNoWebhook URL (max 2048 chars)
callback_metadataobjectNoArbitrary JSON passed through to webhook payload
settingsobjectNoAdditional settings (reserved for future use)
expires_instringNoDuration until expiry. Default: "48h"

expires_in Format

A number followed by a unit: m (minutes), h (hours), or d (days).

ExampleMeaning
"30m"30 minutes
"2h"2 hours
"7d"7 days
nullNo expiry

Field Object

FieldTypeRequiredDescription
keystringYesIdentifier used in response data (e.g. "full_name")
typestringYesOne of the 8 field types
labelstringYesDisplay label (max 255 chars)
descriptionstringNoHelper text shown below label
requiredbooleanNoDefault: false
configobjectNoType-specific options (see Field Types)

Example Request

bash
curl -X POST https://your-server.com/api/v1/forms \
  -H "Authorization: Bearer af_live_..." \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Feedback",
  "fields": [
    {"key": "rating", "type": "number", "label": "Rating (1-5)",
     "required": true, "config": {"min": 1, "max": 5}},
    {"key": "comment", "type": "textarea", "label": "Comment"}
  ],
  "callback_url": "https://your-app.com/webhook",
  "expires_in": "7d"
}'

Response 201 Created

JSON
{
  "id": "01JNXXXXXXXXXXXXXXXXXX",
  "title": "Feedback",
  "description": null,
  "url": "https://your-server.com/f/01JNXXXXXXXXXXXXXXXXXX",
  "status": "active",
  "fields_count": 2,
  "expires_at": "2026-03-12T10:00:00",
  "created_at": "2026-03-05T10:00:00"
}

List Forms

GET /api/v1/forms

List forms for the authenticated account. Results are paginated using cursor-based pagination.

Query Parameters

ParamTypeDefaultDescription
statusstringFilter by status: active, completed, cancelled, expired
cursorstringPagination cursor (last seen form ID)
limitinteger20Max results per page

Response 200 OK

JSON
[
  {
    "id": "01JNXXXXXXXXXXXXXXXXXX",
    "title": "Feedback",
    "description": null,
    "url": "https://your-server.com/f/01JN...",
    "status": "active",
    "fields_count": 2,
    "expires_at": "2026-03-12T10:00:00",
    "created_at": "2026-03-05T10:00:00"
  }
]

Get Form

GET /api/v1/forms/{form_id}

Get detailed information about a form, including its field definitions and callback URL.

Response 200 OK

JSON
{
  "id": "01JNXXXXXXXXXXXXXXXXXX",
  "title": "Feedback",
  "description": null,
  "url": "https://your-server.com/f/01JN...",
  "status": "active",
  "fields_count": 2,
  "expires_at": "2026-03-12T10:00:00",
  "created_at": "2026-03-05T10:00:00",
  "fields": [
    {"key": "rating", "type": "number", "label": "Rating (1-5)",
     "required": true, "config": {"min": 1, "max": 5}},
    {"key": "comment", "type": "textarea", "label": "Comment",
     "required": false, "config": {}}
  ],
  "callback_url": "https://your-app.com/webhook",
  "settings": {}
}

Update Form

PATCH /api/v1/forms/{form_id}

Update a form's status or expiry. All fields are optional.

Request Body

FieldTypeDescription
statusstringSet to "cancelled" to cancel the form
expires_atstringISO 8601 datetime, or null to remove expiry

Example: Cancel a Form

bash
curl -X PATCH https://your-server.com/api/v1/forms/FORM_ID \
  -H "Authorization: Bearer af_live_..." \
  -H "Content-Type: application/json" \
  -d '{"status": "cancelled"}'

Response 200 OK

Returns the updated form object (same schema as Create Form response).

Delete Form

DELETE /api/v1/forms/{form_id}

Permanently delete a form and all associated responses.

Response 204 No Content

Empty response body on success.

List Responses

GET /api/v1/forms/{form_id}/responses

Get all responses for a form, ordered by submission time (newest first).

Response 200 OK

JSON
[
  {
    "id": "01JNYYYYYYYYYYYYYYY",
    "form_id": "01JNXXXXXXXXXXXXXXXXXX",
    "data": {
      "rating": 5,
      "comment": "Great product!"
    },
    "submitted_at": "2026-03-05T12:00:00",
    "metadata": {
      "ip": "203.0.113.42",
      "user_agent": "Mozilla/5.0..."
    }
  }
]

Get Response

GET /api/v1/forms/{form_id}/responses/{response_id}

Get a single response by ID.

Response 200 OK

Returns a single response object (same schema as items in List Responses).

Error Responses

All errors return a JSON body with a detail field.

JSON
{"detail": "Form not found"}
StatusMeaningDetail
401UnauthorizedInvalid or missing API key
403ForbiddenNo credentials provided
404Not FoundForm or response not found
410GoneForm has expired
422Validation ErrorInvalid request body (Pydantic validation detail)

Form Status Values

StatusDescription
activeForm is accepting submissions
completedForm has been submitted (one response per form)
cancelledForm was cancelled via API
expiredForm's expires_at time has passed