Two options: embed snippet or custom fetch. Your call.
Updated March 2026
You want a form in your React app. Two ways to do it. The fast way: a two-line embed.js snippet that drops an iframe into your page. The flexible way: skip the iframe, build your own form, POST directly to Sutrena. Both work with CRA, Vite, Remix, Next.js, whatever you run.
1. Create a form
Use any template or define custom fields. The response gives you a form ID and a hosted URL.
curl -X POST https://sutrena.com/api/forms \
-H "Authorization: Bearer st_trial_abc123" \
-H "Content-Type: application/json" \
-d '{
"templateId": "feedback",
"createDashboard": true
}'2. Option A: Use the embed snippet
Two lines in your component. The script loads async, renders the form inside the target div. Handles styling, validation, success messages. You do not touch any of that.
import { useEffect, useRef } from "react";
export default function EmbeddedForm() {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const script = document.createElement("script");
script.src = "https://sutrena.com/embed.js";
script.dataset.formId = "frm_xyz789";
containerRef.current?.appendChild(script);
return () => { script.remove(); };
}, []);
return <div ref={containerRef} />;
}3. Option B: Build a custom form with fetch
Want full control? Build your own form, POST submissions directly. You own the markup and the React state. Sutrena just stores the data.
"use client";
import { useState } from "react";
export default function FeedbackForm() {
const [sent, setSent] = useState(false);
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const body = Object.fromEntries(new FormData(e.currentTarget));
const res = await fetch(
"https://sutrena.com/api/forms/frm_xyz789/submit",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
}
);
if (res.ok) setSent(true);
}
if (sent) return <p>Thank you for your feedback!</p>;
return (
<form onSubmit={onSubmit}>
<select name="category" required>
<option value="">Select category</option>
<option value="Bug Report">Bug Report</option>
<option value="Feature Request">Feature Request</option>
<option value="Improvement">Improvement</option>
</select>
<select name="rating" required>
{[1, 2, 3, 4, 5].map((n) => (
<option key={n} value={n}>{n}</option>
))}
</select>
<textarea name="feedback" placeholder="Your feedback" required />
<button type="submit">Submit</button>
</form>
);
}4. Handle success and errors
201 on success with a submission ID. 400 on validation errors with a details array. Map those to field-level messages if you want.
const res = await fetch(
"https://sutrena.com/api/forms/frm_xyz789/submit",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
}
);
if (res.ok) {
const { id } = await res.json();
console.log("Submission ID:", id);
} else if (res.status === 400) {
const { error, details } = await res.json();
// details: [{ field: "email", message: "Required" }]
console.error("Validation errors:", details);
} else {
console.error("Unexpected error:", res.status);
}No. It loads async at runtime. About 2 KB. Your React bundle stays the same size.
Both options need client-side JS, so use them in client components. If you want to display submission data server-side, fetch it in a Server Component.
Follows the system color scheme. You can also force light or dark with a theme parameter in the embed URL.
Yes. The submit endpoint allows cross-origin POST from any origin. No proxy needed.
Sutrena is the web runtime for AI agents. Three primitives — pages, forms, and dashboards — accessible through one API. Your agent creates web artifacts, humans interact with them, and your agent gets the data back. Framework-agnostic. Works from any MCP client or HTTP client.
1. Get a trial key (no auth, no signup)
curl -X POST https://sutrena.com/api/trial2. Create a form + dashboard from a template
curl -X POST https://sutrena.com/api/forms \
-H "Authorization: Bearer st_trial_xxx" \
-H "Content-Type: application/json" \
-d '{"templateId": "waitlist", "createDashboard": true}'Get a trial API key instantly with no signup, or create an account for the full experience.