I
Inbound
FeaturesHow it worksPricingDocs
Sign inTry Free

Documentation

Everything you need to collect, manage, and retrieve form submissions with Inbound.

Introduction

Inbound is a form backend. You point any HTML form (or fetch call) at a unique endpoint URL, and Inbound stores the submissions, filters spam, and emails you when new entries arrive — no server code required on your side.

Everything is organized in a simple hierarchy: a project groups related forms and holds shared settings like allowed domains and usage quotas, and each form has its own endpoint, notification settings, and API key.

Quick start

  1. 1Sign up and create a project from the dashboard.
  2. 2Create a form inside the project and copy its endpoint URL.
  3. 3Point your HTML form's action at that URL with method="POST".
  4. 4Submit the form — the entry appears in your dashboard and you get an email notification.
index.html
<form action="https://inbound.drapi.dev/f/{form-id}" method="POST">
  <!-- Honeypot (leave empty) -->
  <input type="hidden" name="_honeypot" value="" style="display:none">

  <input type="text" name="name" placeholder="Your name" required>
  <input type="email" name="email" placeholder="Email" required>
  <textarea name="message" placeholder="Message" required></textarea>

  <button type="submit">Send</button>
</form>

Creating a project

Projects are the top-level container. Each project has its own allowed domains, monthly submission quota, and analytics.

  1. 1Go to Projects in the dashboard sidebar.
  2. 2Click New project and give it a name (e.g. "Portfolio site").
  3. 3Open the project to add forms and configure allowed domains.
On the free plan each project allows 1 form and 100 submissions per month. The quota resets on the first day of each month (UTC).

Allowed domains

Allowed domains restrict where submissions can come from. When a request hits your form endpoint, its Origin / Refererheaders are checked against the project's domain list. Requests from other origins are rejected with 403 DOMAIN_NOT_ALLOWED.

  1. 1Open your project and go to its Settings tab.
  2. 2Add each domain your forms live on, e.g. example.com.
  3. 3Subdomains are matched automatically — blog.example.com is covered by example.com.
If the list is empty, submissions are accepted from anywhere. localhost and 127.0.0.1 are always allowed, so local development keeps working.

Creating a form

Each form gets a unique public ID and an endpoint URL of the shape https://inbound.drapi.dev/f/{form-id}.

  1. 1Inside a project, click New form and name it (e.g. "Contact form").
  2. 2Optionally configure email notifications and a redirect URL.
  3. 3Copy the endpoint URL from the form's Overview tab — integration examples for HTML, React, fetch, cURL and Axios are provided there.

Posting submissions

Send a POST request to your form endpoint. No authentication is needed — the request is validated by origin, rate limits, and spam checks. Accepted content types: application/json, application/x-www-form-urlencoded, and multipart/form-data.

POST /f/{form-id}
curl -X POST 'https://inbound.drapi.dev/f/{form-id}' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Jane Doe","email":"jane@example.com","message":"Hello!"}'

All fields in the body are stored as the submission payload, with two rules:

FieldBehavior
_honeypotSpam trap. Must be empty or absent — a non-empty value rejects the submission. Include it as a hidden field that real users never fill.
_*Any field starting with an underscore is treated as internal and stripped before the payload is stored.

A successful submission returns:

200 OK
{
  "success": true,
  "id": "665f1c2e8b3a4d0012ab34cd",
  "redirectUrl": "https://yoursite.com/thank-you"  // only if configured
}
The payload is limited to 100 KB and each IP can post at most 10 submissions per minute. See the error reference for all failure responses.

Fetching submissions

Besides accepting submissions, every form exposes a read API — useful for building an admin page on your own site that lists everything the form has received. Requests are authenticated with the form's API key, sent as a Bearer token.

GET /f/{form-id}/submissions
curl 'https://inbound.drapi.dev/f/{form-id}/submissions?page=1&limit=25' \
  -H 'Authorization: Bearer inb_your_api_key'

Query parameters:

ParameterDefaultDescription
page1Page number, newest submissions first.
limit25Results per page, maximum 100.
from—Only submissions created at or after this ISO date.
to—Only submissions created at or before this ISO date.
200 OK
{
  "form": { "id": "a1b2c3d4-...", "name": "Contact form" },
  "submissions": [
    {
      "id": "665f1c2e8b3a4d0012ab34cd",
      "data": { "name": "Jane Doe", "email": "jane@example.com", "message": "Hello!" },
      "createdAt": "2026-07-08T09:30:00.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "totalPages": 1 }
}

Example: fetching submissions from your own server to render an admin page.

admin.js
const res = await fetch('https://inbound.drapi.dev/f/{form-id}/submissions?limit=50', {
  headers: { Authorization: `Bearer ${process.env.INBOUND_API_KEY}` },
})
const { submissions, pagination } = await res.json()
Spam-flagged submissions are excluded, and submitter metadata (IP, user agent) is not exposed through this API — view those in your dashboard instead.

API keys

The read API is protected by a secret per-form API key (prefixed inb_). The form's public ID appears in your website's HTML, so it can never grant read access on its own.

  1. 1Open your form and go to the Settings tab.
  2. 2In the API access card, click Generate API key.
  3. 3Copy the key and store it somewhere safe, e.g. an environment variable on your server.

From the same card you can regenerate the key (the old one stops working immediately) or revoke it to disable read access entirely.

Treat the key like a password. Call the read API from your server, not from client-side JavaScript — anything shipped to the browser is public.

Rolling the form ID

If your endpoint URL leaks or starts attracting spam, you can rotate the form's public ID. This generates a brand-new endpoint URL and permanently invalidates the old one — existing submissions are kept.

  1. 1Open your form's Settings tab.
  2. 2In the Form endpoint card, click Roll Form ID and confirm.
  3. 3Update every website that posts to the form with the new URL — the old URL returns 404 immediately.
Rolling the ID does not change your API key, but since the read endpoint contains the form ID, update its URL in your integrations too.

Email notifications

When enabled, every new submission triggers an email. Configure this in the form's Settings tab:

SettingDescription
Recipient emailsUp to 2 addresses on the free plan. Defaults to your account email when empty.
Email subjectCustom subject line. Defaults to "New submission on [form name]".
Sender nameThe name shown in the From field.
Redirect URLWhere the submitter is sent after a successful submission. Leave blank to return JSON.

Pausing submissions

You can temporarily stop accepting submissions without deleting anything. While paused, the endpoint responds with 503 FORM_PAUSED and nothing is stored.

  1. 1Open the form's Settings tab and scroll to the danger zone.
  2. 2Toggle Pause submissions. Flip it back anytime to resume.

Rate limits & quotas

LimitValueScope
Posting submissions10 requests / minutePer IP
Reading submissions60 requests / minutePer IP
Payload size100 KBPer submission
Monthly submissions100 / month (free plan)Per project
Forms1 (free plan)Per project

When a rate limit is hit the API returns 429 with a Retry-After header. The monthly quota resets on the first day of each month (UTC).

Error reference

All errors share the same shape:

{ "error": "ERROR_CODE", "message": "Human-readable description." }

Posting submissions:

CodeHTTPMeaning
NOT_FOUND404Form ID is invalid or the form does not exist.
PAYLOAD_TOO_LARGE413Body exceeds the 100 KB limit.
RATE_LIMITED429More than 10 submissions per minute from one IP.
FORM_PAUSED503The form is currently paused.
DOMAIN_NOT_ALLOWED403Origin/Referer is not in the project’s allowed domains.
SPAM_DETECTED400The honeypot field was filled in.
QUOTA_EXCEEDED429The project’s monthly submission quota is used up.

Fetching submissions:

CodeHTTPMeaning
UNAUTHENTICATED401No Bearer token in the Authorization header.
INVALID_API_KEY401The key is wrong or has been revoked.
NOT_FOUND404Form ID is invalid or the form does not exist.
RATE_LIMITED429More than 60 requests per minute from one IP.

ON THIS PAGE

  • Introduction
  • Quick start
  • Creating a project
  • Allowed domains
  • Creating a form
  • Posting submissions
  • Fetching submissions
  • API keys
  • Rolling the form ID
  • Email notifications
  • Pausing submissions
  • Rate limits & quotas
  • Error reference
I
Inbound

Developer-first HTML form backend with zero server setup, instant spam protection, and real-time notifications.

© 2026 Inbound. All rights reserved.

Product

  • Features
  • How it works
  • Pricing
  • API Reference

Developers

  • Documentation
  • HTML & React Examples
  • Resend Integration
  • Brevo Integration

Resources

  • Privacy Policy
  • Terms of Service
  • GitHub