openapi: 3.1.0
info:
title: AgentForms Agent API
version: "2.0.0"
description: |
Programmatic form lifecycle for AI agents and integrations.
All routes return JSON. Authentication via API key in the Authorization header:
```
Authorization: Bearer afk_live_...
```
Base URL: `https://agentforms.io/api/v2`
Permissions model:
- `read_forms` — list and view forms, versions, analytics
- `write_forms` — create forms, update fields, create API keys
- `read_submissions` — view submissions and analytics
- `delete_forms` — delete forms, revoke API keys
Tier-gated features:
- Free: Basic form CRUD, submissions, analytics
- Starter+: AI form builder, geo/device analytics
- Pro+: Impressions, conversion analytics
Field types: `text`, `email`, `tel`, `textarea`, `select`, `number`, `date`, `hidden`
paths:
/keys:
get:
operationId: listKeys
summary: List all API keys
security:
- BearerAuth: []
responses:
"200":
description: List of API keys
content:
application/json:
schema:
type: object
properties:
keys:
type: array
items:
$ref: '#/components/schemas/ApiKey'
post:
operationId: createKey
summary: Create a new API key
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name:
type: string
description: Human-readable key name
permissions:
type: object
description: Granular permissions (optional)
additionalProperties:
type: boolean
responses:
"201":
description: New API key created
content:
application/json:
schema:
type: object
properties:
id: { type: integer }
key_prefix: { type: string }
full_key: { type: string }
name: { type: string }
permissions: { type: object, nullable: true }
created_at: { type: string, nullable: true }
warning: { type: string }
/keys/{key_id}:
delete:
operationId: revokeKey
summary: Revoke an API key
security:
- BearerAuth: []
parameters:
- in: path
name: key_id
required: true
schema: { type: integer }
responses:
"200":
description: Key revoked
content:
application/json:
schema:
type: object
properties:
revoked: { type: boolean }
id: { type: integer }
/forms:
get:
operationId: listForms
summary: List all forms
security:
- BearerAuth: []
parameters:
- in: query
name: limit
schema: { type: integer, default: 50, maximum: 200 }
- in: query
name: offset
schema: { type: integer, default: 0 }
responses:
"200":
description: Paginated form list
content:
application/json:
schema:
type: object
properties:
forms:
type: array
items: { $ref: '#/components/schemas/FormSummary' }
total: { type: integer }
limit: { type: integer }
offset: { type: integer }
post:
operationId: createForm
summary: Create a new form programmatically
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, fields]
properties:
name:
type: string
description: Form display name
fields:
type: array
minItems: 1
items: { $ref: '#/components/schemas/FieldDefinition' }
metadata:
type: object
nullable: true
description: Arbitrary JSON metadata (e.g., session context)
responses:
"201":
description: Form created
content:
application/json:
schema:
type: object
properties:
id: { type: integer }
token: { type: string }
name: { type: string }
fields:
type: array
items: { $ref: '#/components/schemas/FieldDefinition' }
created_by: { type: string, example: "agent" }
embed_url: { type: string }
submit_url: { type: string }
created_at: { type: string }
/forms/generate:
post:
operationId: generateForm
summary: Generate a form from natural language prompt (AI-powered)
security:
- BearerAuth: []
description: |
Tier-gated (Starter+). Calls the local LLM to generate field definitions
from a natural language description.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [prompt]
properties:
prompt:
type: string
minLength: 5
description: Natural language description of the form
form_name:
type: string
description: Override the generated form name
responses:
"201":
description: AI-generated form created
content:
application/json:
schema:
type: object
properties:
id: { type: integer }
token: { type: string }
name: { type: string }
fields:
type: array
items: { $ref: '#/components/schemas/FieldDefinition' }
field_count: { type: integer }
created_by: { type: string, example: "ai_builder" }
warnings:
type: array
items: { type: string }
embed_url: { type: string }
submit_url: { type: string }
created_at: { type: string }
/forms/suggestions:
post:
operationId: suggestImprovements
summary: Get AI-powered form improvement suggestions
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [form_token]
properties:
form_token:
type: string
context:
type: string
description: Additional context for suggestions
responses:
"200":
description: Improvement suggestions
content:
application/json:
schema:
type: object
properties:
form_id: { type: integer }
form_token: { type: string }
current_field_count: { type: integer }
suggestions:
type: array
items: { type: object }
/forms/{form_token}:
get:
operationId: getForm
summary: Get form details by token
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
responses:
"200":
description: Form details
content:
application/json:
schema:
type: object
properties:
id: { type: integer }
token: { type: string }
name: { type: string }
fields:
type: array
items: { $ref: '#/components/schemas/FieldDefinition' }
field_count: { type: integer }
created_by: { type: string }
metadata:
type: object
nullable: true
honeypot_enabled: { type: boolean }
spam_filter_enabled: { type: boolean }
webhook_enabled: { type: boolean }
rate_limit_enabled: { type: boolean }
embed_url: { type: string }
submit_url: { type: string }
created_at: { type: string }
delete:
operationId: deleteForm
summary: Delete a form and all submissions
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
responses:
"200":
description: Form deleted
content:
application/json:
schema:
type: object
properties:
deleted: { type: boolean }
id: { type: integer }
token: { type: string }
/forms/{form_token}/fields:
put:
operationId: updateFields
summary: Update form fields (replace all)
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [fields]
properties:
fields:
type: array
items: { $ref: '#/components/schemas/FieldDefinition' }
responses:
"200":
description: Fields updated
content:
application/json:
schema:
type: object
properties:
updated: { type: boolean }
fields:
type: array
items: { $ref: '#/components/schemas/FieldDefinition' }
field_count: { type: integer }
/forms/{form_token}/config:
get:
operationId: getFormConfig
summary: Get public form configuration (no auth required)
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
responses:
"200":
description: Public form config for rendering
/forms/{form_token}/submissions:
get:
operationId: listSubmissions
summary: List submissions for a form
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
- in: query
name: limit
schema: { type: integer, default: 50, maximum: 200 }
- in: query
name: offset
schema: { type: integer, default: 0 }
responses:
"200":
description: Paginated submissions
content:
application/json:
schema:
type: object
properties:
submissions:
type: array
items: { $ref: '#/components/schemas/Submission' }
total: { type: integer }
limit: { type: integer }
offset: { type: integer }
/forms/{form_token}/submissions/{sub_id}:
get:
operationId: getSubmission
summary: Get a single submission by ID
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
- in: path
name: sub_id
required: true
schema: { type: integer }
responses:
"200":
description: Single submission
content:
application/json:
schema: { $ref: '#/components/schemas/Submission' }
/forms/{form_token}/analytics:
get:
operationId: getAnalytics
summary: Get form analytics (tier-gated)
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
- in: query
name: days
schema: { type: integer, default: 30, maximum: 90 }
responses:
"200":
description: Analytics data
content:
application/json:
schema:
type: object
properties:
form_id: { type: integer }
form_token: { type: string }
tier: { type: string }
analytics_level: { type: string }
days: { type: integer }
daily_submissions:
type: array
items: { type: object }
summary: { type: object }
geo:
type: array
nullable: true
device:
type: array
nullable: true
impressions:
type: array
nullable: true
/forms/{form_token}/versions:
get:
operationId: listVersions
summary: List version history
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
responses:
"200":
description: Version history
/forms/{form_token}/versions/{version_id}:
get:
operationId: getVersion
summary: Get specific version
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
- in: path
name: version_id
required: true
schema: { type: integer }
responses:
"200":
description: Version details
/forms/{form_token}/versions/{version_id}/rollback:
post:
operationId: rollbackVersion
summary: Roll back to a previous version
security:
- BearerAuth: []
parameters:
- in: path
name: form_token
required: true
schema: { type: string }
- in: path
name: version_id
required: true
schema: { type: integer }
requestBody:
content:
application/json:
schema:
type: object
properties:
reason:
type: string
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: afk_live
schemas:
ApiKey:
type: object
properties:
id: { type: integer }
key_prefix: { type: string }
name: { type: string }
permissions:
type: object
nullable: true
created_at: { type: string }
revoked: { type: boolean }
FormSummary:
type: object
properties:
id: { type: integer }
token: { type: string }
name: { type: string }
field_count: { type: integer }
created_by: { type: string }
created_at: { type: string }
FieldDefinition:
type: object
required: [name, label, type]
properties:
name:
type: string
description: Snake-case field identifier
label:
type: string
description: Human-readable display label
type:
type: string
enum: [text, email, tel, textarea, select, number, date, hidden]
required:
type: boolean
default: false
options:
type: array
items: { type: string }
description: Options for select type
placeholder:
type: string
default:
type: string
Submission:
type: object
properties:
id: { type: integer }
site_id: { type: integer }
submitted_at: { type: string }
data:
type: string
description: Raw JSON string of field data
dynamic_data:
type: object
description: Parsed field data (added by SDK)
client_ip: { type: string }
user_agent: { type: string }
WebhookPayload:
type: object
description: Payload delivered to webhook on form submission
properties:
event:
type: string
example: submission
site_id: { type: integer }
site_name: { type: string }
submission_id: { type: integer }
submitted_at: { type: string }
fields:
type: object
additionalProperties: { type: string }
field_metadata:
type: object
nullable: true
properties:
visible_fields: { type: object }
computed_fields: { type: object }
applied_conditions:
type: array
items: { type: object }