Workspace API

Your form on your own site

Put a Zanfia signup form on any website (WordPress, Webflow, plain HTML) with your own markup and styling: the native form contract, the script, the payload and the error codes.

4 min readLast updated Sep 23, 2026

A Zanfia signup form does not have to live on a Zanfia page or in an iframe. The same native form that Zanfia pages use works on any site you host yourself: you write the HTML and the styles, one script wires the form to your workspace, and the tags, opt-in mode and thank-you redirect come from the form's settings.

1. Get the snippet

The quickest way is the CLI, which prints ready-made markup for a form:

zanfia forms snippet <formId> --lang pl --first-name

Or write it by hand. The minimum is a form tagged with your workspace id and the form id, an e-mail field, a submit button and the script:

<form data-zanfia-form="{workspaceId}/{formId}">
  <label>E-mail<br /><input name="email" type="email" required autocomplete="email" /></label>
  <input name="website" type="text" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px;opacity:0" />
  <button type="submit">Sign me up</button>
  <div data-zanfia-success hidden>Thank you! Check your inbox to confirm.</div>
  <div data-zanfia-error hidden>Something went wrong. Please try again.</div>
</form>
<script src="https://zanfia.co/zanfia-page-forms.js" defer></script>

Your workspace id comes from GET /workspace (or zanfia workspace get), the form id from GET /forms (or zanfia forms list).

2. The contract

The script looks for every form[data-zanfia-form] on the page and takes over its submit. Everything else about the form is yours: tags, classes, layout, CSS.

ElementRequiredWhat it does
data-zanfia-form="{workspaceId}/{formId}"yesWhich form receives the signup.
input[name="email"]yesThe address. The form does nothing when it is empty.
input[name="firstName"]noStored on the client.
input[name="trackingConsent"] (checkbox)noEngagement-tracking consent. Only a ticked box grants it.
input[name="website"]noHoneypot. Keep it visually hidden; a filled value means a bot and nothing is sent.
button[type="submit"]yesGets aria-busy="true" and is disabled while the request runs.
[data-zanfia-success]noShown after a successful signup when there is no redirect; the fields are disabled and the button hidden.
[data-zanfia-error]noShown when the request fails; the button is re-enabled.
data-zanfia-redirect="url" (on the form)noSends the visitor to that URL after a successful signup instead of showing the success state. Absent = the form's own redirectUrl is NOT applied here; set the attribute when you want a redirect.

The script posts to the origin it was loaded from (https://zanfia.co), never to your domain, so nothing has to be proxied. The endpoint answers the browser's cross-origin preflight and accepts any origin: the call is anonymous, carries no cookies, and the ids in the markup are public anyway. Abuse is limited per IP on the platform side.

3. What is sent

POST https://zanfia.co/api/submitForm with a JSON body:

{
  "workspaceId": "work_…",
  "formId": "form_…",
  "email": "reader@example.com",
  "firstName": "Anna",
  "trackingConsent": false,
  "language": "pl"
}

language is the page's <html lang> (or the browser language) and picks the language of the confirmation e-mail. A 200 means the signup was recorded. For a double opt-in form the subscription, the tags and the consent apply only after the reader confirms from the e-mail; a single opt-in form subscribes immediately.

Other responses: 400 invalid payload (e-mail format, unknown form), 404 form not found, 429 too many requests from one IP, 5xx platform error. The script treats anything but 2xx as an error state.

4. After the signup

  • Thank-you page. Put data-zanfia-redirect on the form to send the reader to your own page. The script also stores the address in sessionStorage so a second page carrying a data-zanfia-phone-form (the SMS reminder step) can attach a phone number to the same signup.
  • Pixels. On a successful signup the script dispatches a zanfia:form-submitted event on window with { workspaceId, formId }, so your own tracking can fire a lead.
  • Confirmation e-mail. The sender name and the subject come from the form's confirmation e-mail settings (forms update --confirmation-subject … or the full copy through confirmationEmailOverride).

5. Webinar sessions

A form attached to a live room with rolling sessions can offer a session picker. Add data-zanfia-sessions="{workspaceId}/{roomId}" to the form; the script loads the next sessions from the platform and inserts a select before the submit button.

Was this article helpful?

Related articles

Spotted something off? Tell us at support@zanfia.com.