Skip to content
contact.
FeaturesHow it worksDocsContact
Log inGet started

Guides

  • Getting started
  • Embedding
  • Field types and schema
  • File uploads
  • Delivery and integrations
  • Spam protection and limits
  • API reference
  • Troubleshooting & FAQ

Operations

  • Admin & self-hosting
Open dashboard →
THE QUICK START

From your website to your inbox.

Keep your frontend and your design. Add a little Contact and start collecting submissions in a few minutes.

1. Create a workspace and a form

Create a workspace, then choose New form in your dashboard. Give the form a name and enter the exact origins allowed to submit it, such as https://example.com or http://localhost:3000. An origin is the scheme and host, plus the port when it is not the default, and it never includes a path.

The starter schema accepts a name, email, and message. You can customize the field schema when you create or edit the form. See Field types and schema for the full reference.

2. Copy your endpoint and public key

After saving, your form shows a public key and a submission endpoint. The public key is designed to live in browser code — it identifies the form, not a user. Never place an administrator key or integration secret in frontend code.

ValueExample
Submission endpointhttps://contact.kirandhakal.me/v1/forms/YOUR_PUBLIC_KEY/submissions
MethodPOST with a JSON body
Required headerIdempotency-Key (one per submission)

3. Send a submission

Send JSON from an allowed website origin. A native HTML form POST is not supported, so submit with JavaScript or from your own server. Pick the tab that matches your stack.

<form id="contact">
  <input name="name" placeholder="Name" required />
  <input name="email" type="email" placeholder="Email" required />
  <textarea name="message" placeholder="Message" required></textarea>
  <input type="text" name="_website" tabindex="-1" autocomplete="off" hidden aria-hidden="true" />
  <button type="submit">Send</button>
</form>
<p id="status" role="status"></p>

<script>
  const form = document.getElementById("contact");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const status = document.getElementById("status");
    status.textContent = "Sending…";
    const response = await fetch("https://contact.kirandhakal.me/v1/forms/YOUR_PUBLIC_KEY/submissions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Idempotency-Key": crypto.randomUUID()
      },
      body: JSON.stringify(Object.fromEntries(new FormData(form)))
    });
    const result = await response.json();
    status.textContent = response.ok ? result.message : (result.detail || "Something went wrong.");
    if (response.ok) form.reset();
  });
</script>

Create one Idempotency-Key per submission and reuse the same value if you retry that exact submission. Keys prevent duplicate messages when a network hiccup makes you send twice.

A 202 Accepted response means Contact has stored the submission and queued its delivery rules. It does not mean the confirmation email or SMS has been delivered yet — see Delivery and integrations.

4. Confirm it works

  1. Open your form’s inbox in the dashboard. The new submission should appear immediately.
  2. Check the delivery status of any automatic rules on the submission.
  3. Test from your production origin to confirm the allowlist is correct.
The public key is safe to ship to browsers. Keep admin API keys, SMTP passwords, Twilio tokens, and Slack/Discord webhook URLs on the server only.

Where to go next

  • Embedding — full examples for HTML, React, and Next.js.
  • Field types and schema — validate and shape your data.
  • File uploads — accept attachments safely.
  • Spam protection and limits — honeypot, origins, and rate limits.
NextEmbedding
contact.

Your frontend. Our form backend.

How to useIntegrationsContactTermsPrivacy policy
© 2026 ContactDesigned & developed by Kiran Dhakal