TruForms
Reference

API Reference

All TruForms HTTP endpoints, parameters, and responses.

Last updated

Base URL: https://forms.truenotech.com (all endpoints are under /api/*; the legacy https://api.forms.truenotech.com/submit host still works via a redirect shim).

Most people only need one endpoint: POST /api/submit. Everything else on this page powers the dashboard UI. If you're just embedding a form on your site, head to the Quickstart instead.

All dashboard endpoints require a session cookie (truforms_session) and, for state-changing requests, an X-CSRF-Token header. The public submit endpoint is unauthenticated — it identifies the form by its access key.

POST /api/submit

The public submission endpoint. Accepts either application/json or multipart/form-data.

Required fields

  • access_key (string, UUID) — the form's access key from the dashboard.

Payload

Any other fields are stored as the submission payload. A few field names are reserved:

Name Meaning
access_key Your form ID.
redirect Optional URL to 303-redirect to instead of returning JSON.
botcheck (or whatever you configured) Honeypot. If present and non-empty, the submission is silently marked as spam.
cf-turnstile-response / h-captcha-response / captcha_token Captcha token, verified server-side when captcha is configured.

Response

On success, 200 OK:

{
  "success": true,
  "message": "Form submission received",
  "submissionId": "8b1c1e6a-..."
}

Or a 303 See Other redirect if redirect is set.

Error codes

Status error When
400 MissingAccessKey access_key not present in payload.
400 FileTooLarge / FileTypeNotAllowed Upload violated the form's limits.
402 QuotaExceeded Workspace exceeded monthly submission cap.
402 FeatureUnavailable Feature requires a higher plan.
403 OriginNotAllowed Origin header doesn't match the form's allowed domains.
403 CaptchaMissing / CaptchaFailed Captcha token missing or invalid.
404 InvalidAccessKey Access key doesn't match any form.
422 ValidationError Malformed payload.
429 RateLimited Per-IP (60/min) or per-form (300/min) rate limit hit.

GET /api/auth/me

Returns the current user. Requires session cookie.

{
  "user": {
    "id": "uuid",
    "email": "[email protected]",
    "name": "Alice",
    "emailVerifiedAt": "2026-04-22T10:00:00.000Z",
    "createdAt": "2026-04-01T00:00:00.000Z"
  }
}

GET /api/workspaces

Lists workspaces the current user belongs to, with their role and plan.

GET /api/workspaces/:id/forms

Lists forms in a workspace.

POST /api/workspaces/:id/forms

Creates a form.

{ "name": "Contact form" }

GET /api/forms/:id

Fetches a single form with its settings.

PATCH /api/forms/:id

Updates a form. All fields optional.

{
  "name": "string",
  "settings": { "...partial FormSettings..." },
  "captchaSecretKey": "string | null"
}

When captchaSecretKey is a string, it's encrypted at rest and used to verify captcha tokens on future submissions. Pass null to clear.

DELETE /api/forms/:id

Soft-deletes the form. Access key immediately stops working.

POST /api/forms/:id/rotate-access-key

Generates a new access key. Existing embeds break on the next request.

GET /api/forms/:formId/submissions

Cursor-paginated list.

Query params:

  • cursor (optional) — opaque cursor from previous response.
  • limit (default 50, max 200).
  • includeSpam (default false).

Response:

{
  "items": [ { "id": "...", "payload": {...}, "spamScore": 0, "isSpam": false, "files": [...], "createdAt": "..." } ],
  "nextCursor": "..."
}

GET /api/forms/:formId/submissions/stream

Server-Sent Events stream of new submissions for this form. message events are JSON { id, formId, payload, spamScore, isSpam, createdAt }.

GET /api/forms/:formId/integrations / POST / PATCH /api/integrations/:id / DELETE /api/integrations/:id

Manage outbound integrations. See Integrations.

POST /api/integrations/:id/test

Fires a synthetic submission through the integration so you can verify wiring.

GET /api/integrations/:id/deliveries

Webhook delivery history — attempts, status, HTTP response code, error.

POST /api/billing/webhook/razorpay

Razorpay webhook endpoint. Not for you to call — Razorpay calls it when subscription state changes. Verified via X-Razorpay-Signature.

Rate limits

Public /api/submit:

  • 60 requests / minute / IP
  • 300 requests / minute / form access key

Dashboard API: no explicit rate limit at present; we reserve the right to add one.

Client libraries

We don't ship official SDKs. The API is small enough that fetch works everywhere. If you'd like a typed client, the Zod schemas in @truforms/shared-types can generate one — or ping us.

Further reading

API Reference — TruForms