Form2Workflow

Publishing

JavaScript SDK

Use @form2n8n/sdk when you want your own HTML and JavaScript instead of the rendered widget.

The SDK is not published to npm yet. Until it is, call the submit endpoint directly (below) — it's one fetch call.

Without the SDK#

The submit endpoint is public and CORS-enabled, so any page can post to it:

javascript
const res = await fetch('https://form2wf.com/api/v1/submit/3f1c…form-uuid', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Ada', email: 'ada@example.com' })
});
const result = await res.json();
// 200: { "success": true, "data": <n8n response>, "message": "Submitted successfully" }
// 403 inactive form · 429 quota or rate limit · 502 n8n failed or timed out

Send JSON for plain values, or FormData for file uploads (see multipart payloads). Submissions are rate-limited to 10 per minute per IP.

SDK setup#

javascript
import { Form2n8n } from '@form2n8n/sdk';

const f2 = new Form2n8n({
  apiUrl: 'https://form2wf.com/api/v1',   // always set this — the built-in default is a placeholder
  onError: (err) => console.error(err)
});

SDK methods take the form's UUID (shown in the dashboard URL and returned by list_forms), not its slug.

submit#

const result = await f2.submit('3f1c…form-uuid', {
  name: 'Ada',
  email: 'ada@example.com',
  message: 'Hello'
});
// result = whatever your n8n workflow responded with

The object you pass becomes data in the submit payload. Unlike the widget, the SDK returns n8n's response body, so you can show a result computed by your workflow.

bindForm#

Wire your own <form> element: submission is intercepted and sent as a flat object of its named inputs.

<form id="signup">
  <input name="email" type="email" required>
  <button>Join</button>
</form>
<script type="module">
  f2.bindForm(document.getElementById('signup'), '3f1c…form-uuid', {
    onSuccess: () => alert('Subscribed!'),
    onError: (e) => alert(e.message)
  });
</script>

fetch and poll#

fetch(formId) calls the form's submit webhook with an empty POST and returns data from n8n's reply — handy for small read-only feeds. poll(formId, callback, intervalMs) repeats it and returns a function that stops polling.

const items = await f2.fetch('7b9e…form-uuid');
const stop = f2.poll('7b9e…form-uuid', (items) => render(items), 10000);
// later: stop();

fetch doesn't forward query parameters to n8n and doesn't check login. For parameterized or per-user data, use a form with an onload webhook instead.

Form-user auth#

await f2.auth.login('client@acme.com', 'password', '<organization-id>');
f2.auth.isAuthenticated(); // true
await f2.submit('3f1c…', { request: 'Reset router' }, { auth: true });
f2.auth.logout();

Reference#

MemberDescription
new Form2n8n({ apiUrl, onError })Create a client.
submit(formId, data, { auth, headers })Submit data; resolves to n8n's response.
fetch(formId, { auth })Call the form's webhook for data.
bindForm(el, formId, { auth, headers, onSuccess, onError })Handle a form element's submit event.
poll(formId, callback, intervalMs, options)Repeat fetch; returns a stop function.
auth.login / register / logout / isAuthenticated / getTokenForm-user session helpers.