Docs / API
The form-to-email API
Base URL https://api.conform.centrst.com. No API key, no account. The machine-readable source of truth is the served OpenAPI document; /.well-known/conform.json describes the deployment, and this page is the human summary of both.
Endpoints
| Method & path | Purpose |
|---|---|
POST /v1/routes | Create a form endpoint. Accepts an Idempotency-Key header — retries return the same endpoint. Returns form_id, endpoint, status, a one-time management_token, and next_action. |
GET /v1/routes/{form_id} | Poll status. Refreshes verification, so the route activates as soon as the inbox owner confirms. |
DELETE /v1/routes/{form_id} | Hard-delete a route. Requires Authorization: Bearer <management_token>. |
GET /v1/routes/{form_id}/install | Ready-to-install accessible form code with the endpoint baked in. ?framework=html|js|react|vue|svelte|astro|nextjs, &raw=1 for the bare file. |
POST /f/{form_id} | Submit. JSON, URL-encoded, or multipart text fields. Browser posts get an HTML result page; _redirect sends a 303. |
GET / · /openapi.json · /llms.txt | Discovery: deployment descriptor, full contract, plain-text summary. |
Verification — the one human step
The destination inbox must confirm a verification email before delivery starts. While pending, submissions return 409 inbox_not_verified with a next_action block telling you exactly what to poll. The endpoint URL never changes, so install the form immediately and poll until status is "active".
Errors are a contract
Every non-2xx response is JSON with the same envelope:
{ "success": false, "error": "inbox_not_verified", "message": "…", "retryable": true }
error is a stable machine code from the x-conform-error-codes table in the OpenAPI document; retryable: true means the identical request may succeed later. Codes carry extra fields where useful: rate_limited adds retry_after_seconds, monthly_allowance_exhausted adds used/limit/resets_at. The table, the spec, and the runtime are locked together by CI in the open-source engine.
Reserved submission fields
| Field | Effect |
|---|---|
_subject | Sets the email subject. |
_format=json | Attaches the fields as submission.json. |
email | A valid value becomes the reply-to address. |
_redirect | Absolute https:// URL → 303 See Other after delivery. |
_test | Marks a test: delivered for real with a [Test] subject, consumes one quota unit, response carries test: true and echoes a non-boolean value. A test response without test: true means it was spam-filtered. |
_gotcha, botcheck | Spam traps. Keep them empty; never remove them from generated forms. |
Signed webhooks
Add delivery: {"mode": "webhook"|"both", "webhook": {"url": "https://…"}} at creation to deliver submissions as signed JSON events. The response reveals a whsec_ signing secret exactly once (and again on idempotent replays). Deliveries carry webhook-id/webhook-timestamp/webhook-signature headers in the Standard Webhooks format — deduplicate on webhook-id. Email verification remains required in every mode, and the verification email discloses the webhook URL. There is no durable retry queue, because redelivery would require storing submission content: webhook-only routes deliver synchronously and roll back quota on failure (502 webhook_delivery_failed, safe to retry); in both mode the email is authoritative and the webhook is best-effort.
Quota
Every form delivering to the same inbox shares one monthly allowance (250 deliveries free). Successful responses report used and limit; exhaustion returns 429 with resets_at.