{% extends 'base.html' %}
{% block title %}API Docs — AgentForms{% endblock %}
{% block head_extra %}
<meta name="description" content="Complete API reference for building, managing, and submitting forms programmatically.">
<link rel="canonical" href="https://agentforms.io/api/docs">
<style nonce="{{ csp_nonce }}">
/* ---- API docs page-specific ---- */
/* HERO */
.hero {
padding: 120px 0 80px;
text-align: center;
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: -200px; left: 50%; transform: translateX(-50%);
width: 600px; height: 600px;
background: radial-gradient(ellipse, var(--accent-dim) 0%, transparent 70%);
pointer-events: none;
}
.badge {
display: inline-flex; align-items: center; gap: 8px;
padding: 6px 16px;
background: rgba(16, 185, 129, 0.06);
border: 1px solid rgba(16, 185, 129, 0.2);
border-radius: 6px;
font-size: 12px; color: var(--accent);
margin-bottom: 24px;
font-family: var(--mono);
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.badge-dot {
width: 6px; height: 6px; border-radius: 50%;
background: var(--accent);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.hero h1 {
font-size: clamp(32px, 5vw, 56px);
font-weight: 700;
line-height: 1.08;
letter-spacing: -0.03em;
margin-bottom: 16px;
color: var(--text);
}
.hero-sub {
font-size: clamp(15px, 1.8vw, 18px);
color: var(--text-muted);
max-width: 520px;
margin: 0 auto;
line-height: 1.5;
}
/* AUTH CALLOUT */
.auth-callout {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 24px 28px;
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
margin-top: 48px;
max-width: 640px;
margin-left: auto;
margin-right: auto;
}
.auth-callout h3 {
font-size: 15px;
font-weight: 600;
color: var(--text);
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.auth-callout p {
font-size: 14px;
color: var(--text-muted);
line-height: 1.55;
}
.auth-callout a {
color: var(--accent);
text-decoration: none;
}
.auth-callout a:hover {
text-decoration: underline;
}
.auth-callout .code-block {
margin: 12px 0 0;
max-width: 100%;
}
/* ENDPOINT CARD */
.endpoint-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 24px 28px;
margin-bottom: 16px;
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
transition: border-color 0.2s, box-shadow 0.2s;
}
.endpoint-card:hover {
border-color: var(--border-light);
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
}
.endpoint-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 10px;
flex-wrap: wrap;
}
.method {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 4px 12px;
border-radius: 5px;
font-weight: 700;
font-size: 12px;
font-family: var(--mono);
letter-spacing: 0.04em;
min-width: 56px;
}
.method-get {
background: rgba(34, 197, 94, 0.1);
color: #16a34a;
}
.method-post {
background: rgba(16, 185, 129, 0.1);
color: var(--accent-bright);
}
.method-put {
background: rgba(245, 158, 11, 0.1);
color: #d97706;
}
.method-delete {
background: rgba(239, 68, 68, 0.1);
color: #dc2626;
}
.endpoint-url {
font-family: var(--mono);
font-size: 14px;
color: var(--text);
background: var(--bg-elevated);
padding: 5px 12px;
border-radius: 5px;
border: 1px solid var(--border);
}
.endpoint-desc {
font-size: 14px;
color: var(--text-muted);
line-height: 1.5;
}
/* PARAMS TABLE */
.params-table {
margin-top: 16px;
width: 100%;
}
.params-table-title {
font-size: 13px;
font-weight: 600;
color: var(--text);
margin-bottom: 10px;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.param-row {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 0;
border-bottom: 1px solid var(--border);
font-size: 14px;
}
.param-row:last-child {
border-bottom: none;
}
.param-name {
font-family: var(--mono);
font-size: 13px;
color: var(--accent);
font-weight: 500;
min-width: 180px;
}
.param-type {
font-family: var(--mono);
font-size: 12px;
color: var(--text-muted);
background: var(--bg-elevated);
padding: 2px 8px;
border-radius: 4px;
border: 1px solid var(--border);
white-space: nowrap;
}
.param-desc {
flex: 1;
color: var(--text-muted);
font-size: 13px;
}
.param-required {
font-size: 11px;
color: #ef4444;
font-weight: 600;
text-transform: uppercase;
}
/* CODE BLOCK overrides for inline use */
.code-inline {
background: #1e1e2e;
border: 1px solid #313244;
border-radius: 8px;
overflow: hidden;
margin: 16px 0;
}
.code-inline pre {
padding: 20px 24px;
overflow-x: auto;
font-family: var(--mono);
font-size: 13px;
line-height: 1.65;
color: #cdd6f4;
}
.code-inline pre .kw { color: #cba6f7; }
.code-inline pre .str { color: #a6e3a1; }
.code-inline pre .cm { color: #6c7086; }
.code-inline pre .fn { color: #89b4fa; }
.code-inline pre .num { color: #f9e2af; }
/* EXAMPLES */
.example-block {
margin-bottom: 32px;
}
.example-block:last-child {
margin-bottom: 0;
}
.example-block h3 {
font-size: 16px;
font-weight: 600;
color: var(--text);
margin-bottom: 12px;
}
/* RESOURCE LIST */
.resource-list {
list-style: none;
padding: 0;
}
.resource-list li {
padding: 12px 0;
border-bottom: 1px solid var(--border);
font-size: 14px;
display: flex;
align-items: center;
gap: 12px;
}
.resource-list li:last-child {
border-bottom: none;
}
.resource-list dt {
font-weight: 600;
color: var(--text);
min-width: 140px;
}
.resource-list dd {
color: var(--text-muted);
margin: 0;
}
.resource-list a {
color: var(--accent);
text-decoration: none;
font-family: var(--mono);
font-size: 13px;
}
.resource-list a:hover {
text-decoration: underline;
}
/* RESPONSIVE */
@media (max-width: 768px) {
.hero { padding: 90px 0 50px; }
.hero h1 { font-size: 28px; }
.hero-sub { font-size: 14px; }
.auth-callout { padding: 16px 20px; margin-top: 32px; }
.endpoint-card { padding: 16px 20px; }
.endpoint-url { font-size: 12px; word-break: break-all; }
.param-name { min-width: 120px; font-size: 12px; }
.param-desc { font-size: 12px; }
.param-required { font-size: 10px; }
.params-table-title { font-size: 11px; }
.example-block h3 { font-size: 14px; }
.code-inline pre { padding: 16px; font-size: 12px; }
.section-header { margin-bottom: 32px; }
.resource-list .param-name { min-width: 100px; font-size: 12px; }
.resource-list .param-desc { font-size: 12px; }
}
@media (max-width: 480px) {
.hero { padding: 70px 0 40px; }
.hero h1 { font-size: 24px; }
.hero-sub { font-size: 13px; }
.badge { font-size: 10px; padding: 4px 12px; margin-bottom: 16px; }
.auth-callout { padding: 14px 16px; }
.auth-callout h3 { font-size: 13px; }
.auth-callout p { font-size: 12px; }
.endpoint-card { padding: 14px 16px; }
.endpoint-header { gap: 6px; }
.method { padding: 3px 8px; font-size: 11px; min-width: 48px; }
.endpoint-url { font-size: 11px; padding: 4px 8px; word-break: break-all; }
.endpoint-desc { font-size: 12px; }
.param-row { flex-wrap: wrap; gap: 8px; padding: 6px 0; }
.param-name { min-width: 100%; font-size: 12px; margin-bottom: 2px; }
.param-type { font-size: 11px; }
.param-desc { width: 100%; margin-left: 0; }
.param-required { margin-left: auto; }
.code-inline { margin: 12px 0; }
.code-inline pre { padding: 12px; font-size: 11px; line-height: 1.5; }
.example-block { margin-bottom: 24px; }
.example-block h3 { font-size: 14px; margin-bottom: 8px; }
.section-title { font-size: 22px; }
.section-sub { font-size: 13px; }
.resource-list .param-row { flex-wrap: wrap; }
.resource-list .param-name { min-width: 100%; font-size: 12px; }
.resource-list .param-desc { font-size: 12px; }
}
</style>
{% endblock %}
{% block content %}
<!-- HERO -->
<section class="hero">
<div class="container">
<div class="badge">
<span class="badge-dot"></span>
API Reference v2.0
</div>
<h1>AgentForms API</h1>
<p class="hero-sub">Build, manage, and submit forms programmatically. RESTful endpoints with JSON responses, email templates, campaigns, and real-time analytics.</p>
<!-- AUTH CALLOUT -->
<div class="auth-callout">
<h3>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
Authentication
</h3>
<p>All API requests require authentication. Include your API key in the <code>Authorization</code> header:</p>
<div class="code-inline">
<pre><code>Authorization: Bearer YOUR_API_KEY_HERE</code></pre>
</div>
<p style="margin-top: 12px;">Generate API keys in your <a href="/settings/api-keys">account settings</a>.</p>
</div>
</div>
</section>
<!-- ENDPOINTS -->
<section>
<div class="container">
<div class="section-header">
<p class="section-label">Endpoints</p>
<h2 class="section-title">API Reference</h2>
<p class="section-sub">All endpoints use the base URL <code>https://agentforms.io</code>.</p>
</div>
<!-- GET /api/v2/forms -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms</span>
</div>
<p class="endpoint-desc">List all forms for the authenticated user.</p>
</div>
<!-- POST /api/v2/forms -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-post">POST</span>
<span class="endpoint-url">/api/v2/forms</span>
</div>
<p class="endpoint-desc">Create a new form.</p>
</div>
<!-- GET /api/v2/forms/{formToken} -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms/{formToken}</span>
</div>
<p class="endpoint-desc">Get form details by token.</p>
<div class="params-table">
<p class="params-table-title">Parameters</p>
<div class="param-row">
<span class="param-name">formToken</span>
<span class="param-type">string</span>
<span class="param-desc">Form token (path parameter)</span>
<span class="param-required">required</span>
</div>
</div>
</div>
<!-- GET /api/v2/forms/{formToken}/config -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms/{formToken}/config</span>
</div>
<p class="endpoint-desc">Get form field configuration.</p>
</div>
<!-- GET /api/v2/forms/{formToken}/submissions -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms/{formToken}/submissions</span>
</div>
<p class="endpoint-desc">List form submissions for a specific form.</p>
<div class="params-table">
<p class="params-table-title">Parameters</p>
<div class="param-row">
<span class="param-name">formToken</span>
<span class="param-type">string</span>
<span class="param-desc">Form token (path parameter)</span>
<span class="param-required">required</span>
</div>
<div class="param-row">
<span class="param-name">limit</span>
<span class="param-type">integer</span>
<span class="param-desc">Max results per page (default: 50)</span>
</div>
<div class="param-row">
<span class="param-name">offset</span>
<span class="param-type">integer</span>
<span class="param-desc">Pagination offset (default: 0)</span>
</div>
</div>
</div>
<!-- GET /api/v2/forms/{formToken}/submissions/{subId} -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms/{formToken}/submissions/{subId}</span>
</div>
<p class="endpoint-desc">Retrieve a single submission by ID.</p>
<div class="params-table">
<p class="params-table-title">Parameters</p>
<div class="param-row">
<span class="param-name">formToken</span>
<span class="param-type">string</span>
<span class="param-desc">Form token</span>
<span class="param-required">required</span>
</div>
<div class="param-row">
<span class="param-name">subId</span>
<span class="param-type">integer</span>
<span class="param-desc">Submission ID</span>
<span class="param-required">required</span>
</div>
</div>
</div>
<!-- GET /api/v2/forms/{formToken}/analytics -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/forms/{formToken}/analytics</span>
</div>
<p class="endpoint-desc">Get analytics data for a form.</p>
</div>
<!-- POST /api/v2/forms/{formToken}/fields -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-put">PUT</span>
<span class="endpoint-url">/api/v2/forms/{formToken}/fields</span>
</div>
<p class="endpoint-desc">Update form field configuration.</p>
</div>
<!-- Public Submission Endpoint -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-post">POST</span>
<span class="endpoint-url">/api/submit</span>
</div>
<p class="endpoint-desc">Public endpoint for submitting form data. Use your form's token as a query parameter.</p>
<div class="params-table">
<p class="params-table-title">Query Parameters</p>
<div class="param-row">
<span class="param-name">token</span>
<span class="param-type">string</span>
<span class="param-desc">Your form's unique token</span>
<span class="param-required">required</span>
</div>
</div>
<div class="params-table">
<p class="params-table-title">Request Body</p>
<div class="param-row">
<span class="param-name">data</span>
<span class="param-type">object</span>
<span class="param-desc">Key-value pairs matching your form fields</span>
<span class="param-required">required</span>
</div>
</div>
</div>
<!-- Email Templates -->
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-get">GET</span>
<span class="endpoint-url">/api/v2/templates</span>
</div>
<p class="endpoint-desc">List available email templates.</p>
</div>
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-post">POST</span>
<span class="endpoint-url">/api/v2/templates</span>
</div>
<p class="endpoint-desc">Create a new email template.</p>
</div>
<div class="endpoint-card">
<div class="endpoint-header">
<span class="method method-post">POST</span>
<span class="endpoint-url">/api/v2/templates/render</span>
</div>
<p class="endpoint-desc">Render an email template with data.</p>
</div>
</div>
</section>
<!-- EXAMPLES -->
<section>
<div class="container">
<div class="section-header">
<p class="section-label">Examples</p>
<h2 class="section-title">Quick Start</h2>
<p class="section-sub">Copy-paste examples to get up and running.</p>
</div>
<div class="example-block">
<h3>Submit Form Data (Public)</h3>
<div class="code-inline">
<pre><code>curl -X POST "https://agentforms.io/api/submit?token=YOUR_FORM_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "message": "Hello!"}'</code></pre>
</div>
</div>
<div class="example-block">
<h3>List Forms</h3>
<div class="code-inline">
<pre><code>curl -X GET https://agentforms.io/api/v2/forms \
-H "Authorization: Bearer YOUR_API_KEY"</code></pre>
</div>
</div>
<div class="example-block">
<h3>Get Submissions</h3>
<div class="code-inline">
<pre><code>curl -X GET "https://agentforms.io/api/v2/forms/{formToken}/submissions?limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"</code></pre>
</div>
</div>
<div class="example-block">
<h3>Get Analytics</h3>
<div class="code-inline">
<pre><code>curl -X GET https://agentforms.io/api/v2/forms/{formToken}/analytics \
-H "Authorization: Bearer YOUR_API_KEY"</code></pre>
</div>
</div>
</div>
</section>
<!-- RESOURCES -->
<section>
<div class="container">
<div class="section-header">
<p class="section-label">Resources</p>
<h2 class="section-title">More Info</h2>
</div>
<div class="endpoint-card" style="max-width: 640px;">
<dl class="resource-list">
<div class="param-row">
<span class="param-name">Base URL</span>
<span class="param-desc">https://agentforms.io</span>
</div>
<div class="param-row">
<span class="param-name">OpenAPI Spec</span>
<span class="param-desc"><a href="/api/docs/openapi.json">/api/docs/openapi.json</a></span>
</div>
<div class="param-row">
<span class="param-name">Support</span>
<span class="param-desc"><a href="mailto:agentforms@protonmail.com">Contact Support</a></span>
</div>
<div class="param-row">
<span class="param-name">Status</span>
<span class="param-desc"><a href="/health">System Status</a></span>
</div>
</dl>
</div>
</div>
</section>
</div>
{% endblock %}