# Surface Forms SDK



The Forms SDK lets you build a Surface form as a page you own. The form record on Surface stays the data model; your HTML, CSS, and JavaScript own every pixel and every navigation decision. Unlike [embedding](/docs/form-embedding/inline), Surface never sees or serves your markup, yet still gets every response, partial save, booking, and analytics event.

## What you get [#what-you-get]

<CardGroup cols="2">
  <Card title="Your markup, bound with data attributes" icon="code">
    `data-question-id` and friends; the SDK captures answers and saves progress.
  </Card>

  <Card title="Headless engine and React hook" icon="react">
    Drive everything from code, or use `useSurfaceForm`. Also runs in Node.
  </Card>

  <Card title="Embedded schedulers" icon="calendar-check">
    One call renders any supported provider; bookings save automatically.
  </Card>

  <Card title="Tracking and attribution built in" icon="chart-line">
    GTM, GA4, Meta Pixel, HubSpot, and ad conversions fire from the form's settings.
  </Card>

  <Card title="Email validation and enrichment" icon="user-check">
    Deliverability verdicts and real-time lead enrichment.
  </Card>

  <Card title="Built for AI-assisted authoring" icon="wand-magic-sparkles">
    The MCP server creates the record, hands over the binding contract, and validates the HTML.
  </Card>
</CardGroup>

About 22 kB gzipped, zero runtime dependencies, and every request is a CORS simple request (no preflights).

## How it works [#how-it-works]

1. **The form record lives on Surface**, created in the dashboard's SDK form builder or with the [MCP tools](/docs/forms-sdk/building-with-ai). It declares steps, questions, answer shapes, and endings; styling and routing belong to your page.
2. **Your page binds to the record.** `SurfaceForms.init` fetches the runtime configuration; the `data-*` layer captures answers from your inputs, or your code sets them directly.
3. **The SDK writes responses.** Partial saves run in the background; the finishing write on submit is awaited.

```js
import { SurfaceForms } from "@surface-labs/forms-sdk";

const form = await SurfaceForms.init({
  environmentId: "env_xxx",
  formId: "form_xxx",
  apiBaseUrl: "https://forms.withsurface.com", // your environment's host
  container: document.querySelector("#form"),
});
```

## When to use the SDK [#when-to-use-the-sdk]

| Use case                                                                 | Recommendation                                      |
| ------------------------------------------------------------------------ | --------------------------------------------------- |
| A form that must match your site's design system exactly                 | Forms SDK                                           |
| A form inside a React, Vue, or Svelte app with its own state and routing | Forms SDK                                           |
| Conditional flow logic that lives in your codebase                       | Forms SDK                                           |
| A standard form live in minutes with the visual builder                  | [Hosted form or embed](/docs/form-embedding/inline) |
| A marketing pane, hosted URL, custom domain, or A/B-ready styling        | Hosted form or embed                                |

SDK forms skip hosted-page settings (language, custom domain, password, SEO, Turnstile). Responses, workflows, analytics, lead scoring, and integrations work the same as any other Surface form.

## Documentation map [#documentation-map]

<CardGroup cols="2">
  <Card title="Quickstart" icon="rocket" href="/docs/forms-sdk/quickstart">
    A working form on your page.
  </Card>

  <Card title="Binding contract" icon="list-check" href="/docs/forms-sdk/binding">
    The data attribute vocabulary.
  </Card>

  <Card title="Navigation" icon="diagram-project" href="/docs/forms-sdk/navigation">
    Buttons, branching, and submit semantics.
  </Card>

  <Card title="Headless and React" icon="react" href="/docs/forms-sdk/headless-and-react">
    The form handle API and the React adapter.
  </Card>

  <Card title="Schedulers" icon="calendar-check" href="/docs/forms-sdk/schedulers">
    Embedded booking for every provider.
  </Card>

  <Card title="Building with AI" icon="wand-magic-sparkles" href="/docs/forms-sdk/building-with-ai">
    The MCP authoring loop.
  </Card>
</CardGroup>

<Note>
  The npm package ships agent-ready docs (`llms.txt`, `docs/api.md`) and an installable skill in `skills/surface-forms-sdk/`.
</Note>
