FormFlow
EN
Start free
Docs/ API/ API overview

API overview

Base URL, authentication with submission and management keys, and how errors are shaped.

The FormFlow API is a plain REST API served from Cloudflare’s edge.

https://api.formflow.cc

Two surfaces share that host:

  • IngestPOST /v1/f/:slug, the public endpoint your forms post to. See Submission ingest.
  • Management/v1/forms, /v1/webhooks, /v1/api-keys, … — everything the console does, available to scripts and CI.

The OpenAPI 3.1 schema is published at /openapi, and GET /v1/health answers with a plain status object if you want something to point a monitor at.

Authentication

API keys are created in the console under API keys. The full key is shown exactly once at creation — store it in your secret manager; only a prefix is kept on our side. Keys can be revoked at any time.

There are two key types, distinguishable by prefix:

PrefixTypeUse it for
ff_sub_Submission keyServer-side posts to the ingest endpoint. Optional — public forms accept anonymous posts and rely on the anti-spam layer.
ff_mgmt_Management keyThe management API: forms, submissions, webhooks, keys, usage.

Send the key as a bearer token:

curl https://api.formflow.cc/v1/forms \
  -H "Authorization: Bearer ff_mgmt_..."

Keep the two concerns separate: a submission key embedded in a backend that posts forms can’t read your data or change configuration, and you can rotate each independently.

Errors

Every error is an RFC 7807 application/problem+json document:

{
  "type": "https://formflow.cc/problems/rate-limited",
  "title": "Too many submissions",
  "status": 429,
  "detail": "Rate limit exceeded. Try again shortly."
}

type is a stable URL-shaped identifier — branch on it (or on the trailing slug) rather than on title/detail, which are human-readable and may change. Some problems carry extra fields, e.g. quota-exceeded includes your plan’s limit.

Codes you’ll meet most often:

StatusProblemWhen
400bad-bodyBody isn’t parseable as form data or JSON.
402quota-exceededMonthly submission quota used up.
403form-not-liveForm is paused or draft.
403invalid-keyBearer key is invalid or revoked.
403turnstile-failedTurnstile is enabled and the token didn’t verify.
404form-not-foundNo form with that slug.
413file-too-largeAn attachment exceeds your plan’s per-file limit.
429rate-limitedPer-IP rate limit hit (ingest), or key minting cap.

Idempotency

POST /v1/f/:slug accepts an Idempotency-Key header. Replaying the same key for the same form within 24 hours returns the original submission id instead of creating a duplicate — see Submission ingest for the exact semantics.

Conventions

  • Timestamps are ISO-8601 UTC strings: 2026-06-10T10:23:00.000Z.
  • IDs are prefixed strings: frm_… (forms), sub_… (submissions), wh_… (webhooks), whd_… (webhook deliveries).
  • Responses are application/json; list endpoints wrap rows in { "data": [...] }.
Last updated: June 10, 2026