---
title: "Forminit JS SDK Reference"
description: "Install and use the Forminit JavaScript SDK to submit forms, handle file uploads, and manage submissions in any framework."
url: https://forminit.com/docs/sdk/
---

# Forminit JS SDK Reference

The official JavaScript/TypeScript SDK for [Forminit](https://forminit.com) form backend service.

---

## Installation

```bash
# npm
npm install forminit

# yarn
yarn add forminit

# pnpm
pnpm add forminit
```

### CDN (Browser)

```html
<script src="https://forminit.com/sdk/v1/forminit.js"></script>
```

---

## Quick Start

### Browser (with Proxy)

```javascript
const forminit = new Forminit({ proxyUrl: '/api/forminit' });

const form = document.getElementById('contact-form');
form.addEventListener('submit', async (e) => {
  e.preventDefault();
  
  const formData = new FormData(form);
  const { data, error } = await forminit.submit('YOUR_FORM_ID', formData);
  
  if (error) {
    console.error(error.message);
    return;
  }
  
  console.log('Submission ID:', data.hashId);
});
```

### Server-side (Node.js)

For Express and other Node.js backends, see the [Node.js guide](https://forminit.com/docs/nodejs/).

```javascript
import { Forminit } from 'forminit';

const forminit = new Forminit({
  apiKey: process.env.FORMINIT_API_KEY,
});

const { data, error } = await forminit.submit('YOUR_FORM_ID', {
  blocks: [
    {
      type: 'sender',
      properties: {
        email: 'john@example.com',
        firstName: 'John',
        lastName: 'Doe',
      },
    },
    {
      type: 'text',
      name: 'message',
      value: 'Hello world',
    },
  ],
});
```

---

## Configuration

| Option | Type | Description |
|--------|------|-------------|
| `proxyUrl` | string | Client-side proxy URL to protect API key |
| `apiKey` | string | Server-side API key for authentication |

**Client-side:**

```javascript
const forminit = new Forminit({ proxyUrl: '/api/forminit' });
```

**Server-side:**

```javascript
const forminit = new Forminit({ apiKey: process.env.FORMINIT_API_KEY });
```

---

## Class: Forminit

### Constructor

```typescript
new Forminit(config?)
```

**Options:**

| Option | Type | Description |
|--------|------|-------------|
| `proxyUrl` | string | Client-side proxy URL to protect API key |
| `apiKey` | string | Server-side API key for authentication |

### Methods

#### submit()

```javascript
forminit.submit(formId, data)
```

Submits form data to Forminit.

**Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `formId` | string | Your Forminit form ID |
| `data` | FormData or object | Form data to submit |

**Returns:** Promise with `{ data, redirectUrl, error }`

#### setUserInfo()

```javascript
forminit.setUserInfo({ ip, userAgent, referer })
```

Sets user information for server-side submissions. Used when submitting on behalf of a user.

**Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `ip` | string | User's IP address |
| `userAgent` | string | User's browser user agent |
| `referer` | string | Referring page URL |

---

## Submission Formats

### FormData

Use standard HTML form field naming with the `fi-` prefix:

```html
<form id="contact-form">
  <input type="email" name="fi-sender-email" required />
  <input type="text" name="fi-sender-firstName" required />
  <input type="text" name="fi-sender-lastName" required />
  <textarea name="fi-text-message" required></textarea>
  <button type="submit">Send</button>
</form>
```

**Field Naming Patterns:**

| Block Type | Pattern | Example |
|------------|---------|---------|
| Sender properties | `fi-sender-{property}` | `fi-sender-email` |
| Text | `fi-text-{name}` | `fi-text-message` |
| Number | `fi-number-{name}` | `fi-number-quantity` |
| Email | `fi-email-{name}` | `fi-email-invitee` |
| Phone | `fi-phone-{name}` | `fi-phone-emergency` |
| URL | `fi-url-{name}` | `fi-url-website` |
| Date | `fi-date-{name}` | `fi-date-appointment` |
| Rating | `fi-rating-{name}` | `fi-rating-satisfaction` |
| Select | `fi-select-{name}` | `fi-select-plan` |
| Radio | `fi-radio-{name}` | `fi-radio-priority` |
| Checkbox | `fi-checkbox-{name}` | `fi-checkbox-features` |
| File | `fi-file-{name}` | `fi-file-resume` |
| Country | `fi-country-{name}` | `fi-country-shipping` |

### JSON

```typescript
{
  blocks: [
    {
      type: 'sender',
      properties: {
        email: 'john@example.com',
        firstName: 'John',
        lastName: 'Doe',
      },
    },
    {
      type: 'text',
      name: 'message',
      value: 'Hello world',
    },
  ],
}
```

> **Note:** JSON submissions do not support file uploads. Use FormData for forms with files.

---

## Block Types

### Sender Block (Object Block)

Collects submitter information. Can only appear once per submission.

```typescript
{
  type: 'sender',
  properties: {
    email?: string;       // Email address
    firstName?: string;   // First name
    lastName?: string;    // Last name
    fullName?: string;    // Full name
    phone?: string;       // Phone (E.164 format)
    userId?: string;      // User ID from your system
    company?: string;     // Company name
    position?: string;    // Job title
    address?: string;     // Street address
    city?: string;        // City
    country?: string;     // Country (ISO alpha-2)
    title?: string;       // Title (Mr, Mrs, Dr, Prof)
  }
}
```

At least one of `userId`, `email`, `phone`, `firstName`, `lastName`, or `fullName` is required.

### Tracking Block (Object Block)

Captures UTM parameters and attribution data. Can only appear once per submission.

```typescript
{
  type: 'tracking',
  properties: {
    utmSource?: string;
    utmMedium?: string;
    utmCampaign?: string;
    utmTerm?: string;
    utmContent?: string;
    referrer?: string;
    gclid?: string;       // Google Ads
    fbclid?: string;      // Facebook
    msclkid?: string;     // Microsoft Ads
    ttclid?: string;      // TikTok
    // ... other ad platform IDs
  }
}
```

> **Note:** The SDK automatically captures UTM parameters from the URL on client-side.

### Field Blocks

Each field block requires a unique `name` identifier.

```typescript
// Text
{ type: 'text', name: 'message', value: 'Hello world' }

// Number
{ type: 'number', name: 'quantity', value: 10 }

// Email
{ type: 'email', name: 'invitee', value: 'friend@example.com' }

// Phone (E.164 format)
{ type: 'phone', name: 'emergency', value: '+12025550123' }

// URL
{ type: 'url', name: 'website', value: 'https://example.com' }

// Date (ISO 8601)
{ type: 'date', name: 'appointment', value: '2025-01-15' }

// Rating (1-5)
{ type: 'rating', name: 'satisfaction', value: 5 }

// Select (dropdown single or multi)
{ type: 'select', name: 'plan', value: 'Pro' }
{ type: 'select', name: 'services', value: ['web', 'seo'] }

// Radio (single choice)
{ type: 'radio', name: 'priority', value: 'high' }

// Checkbox (single or multi-choice)
{ type: 'checkbox', name: 'newsletter', value: 'yes' }
{ type: 'checkbox', name: 'features', value: ['api', 'support'] }

// Country (ISO 3166-1 alpha-2)
{ type: 'country', name: 'shipping', value: 'US' }
```

---

## Response

### Success Response

```json
{
  "data": {
    "hashId": "7LMIBoYY74JOCp1k",
    "date": "2026-01-01 21:10:24",
    "blocks": {
      "sender": {
        "firstName": "John",
        "lastName": "Doe",
        "email": "john@example.com"
      },
      "message": "Hello world"
    }
  },
  "redirectUrl": "https://forminit.com/thank-you"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `data.hashId` | string | Unique submission identifier |
| `data.date` | string | Submission timestamp |
| `data.blocks` | object | Submitted field values |
| `redirectUrl` | string | Thank you page URL |

### Error Response

```json
{
  "error": {
    "success": false,
    "error": "FI_SCHEMA_FORMAT_EMAIL",
    "code": 400,
    "message": "Invalid email format"
  }
}
```

| Field | Type | Description |
|-------|------|-------------|
| `error.error` | string | Error code |
| `error.code` | number | HTTP status code |
| `error.message` | string | Human-readable message |

---

## Framework Integrations

### Next.js

Create an API route to proxy requests:

```typescript
// app/api/forminit/route.ts
import { createForminitProxy } from 'forminit/next';

const forminit = createForminitProxy({
  apiKey: process.env.FORMINIT_API_KEY!,
});

export const POST = forminit.POST;
```

Use in your component:

```typescript
'use client';

import { Forminit } from 'forminit';

const forminit = new Forminit({ proxyUrl: '/api/forminit' });

// Submit form...
```

### Nuxt.js

Create a server API route:

```typescript
// server/api/forminit.post.ts
import { createForminitNuxtHandler } from 'forminit/nuxt';

const config = useRuntimeConfig();

export default defineEventHandler(
  createForminitNuxtHandler({
    apiKey: config.forminitApiKey,
  })
);
```

Configure runtime config:

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    forminitApiKey: process.env.FORMINIT_API_KEY,
  },
});
```

Use in your component:

```typescript
import { Forminit } from 'forminit';

const forminit = new Forminit({ proxyUrl: '/api/forminit' });

// Submit form...
```

---

## Automatic Tracking

On client-side, the SDK automatically captures URL parameters:

| URL Parameter | Captured As |
|---------------|-------------|
| `utm_source` | `utmSource` |
| `utm_medium` | `utmMedium` |
| `utm_campaign` | `utmCampaign` |
| `utm_term` | `utmTerm` |
| `utm_content` | `utmContent` |
| `gclid` | `gclid` |
| `fbclid` | `fbclid` |
| `msclkid` | `msclkid` |
| `ttclid` | `ttclid` |
| `twclid` | `twclid` |

---

## Error Codes

| Error Code | Status | Description |
|------------|--------|-------------|
| `MISSING_API_KEY` | 401 | Server-side call without API key |
| `FORM_NOT_FOUND` | 404 | Form ID does not exist |
| `FORM_DISABLED` | 403 | Form is currently disabled |
| `EMPTY_SUBMISSION` | 400 | No fields with values submitted |
| `FI_SCHEMA_FORMAT_EMAIL` | 400 | Invalid email format |
| `FI_RULES_PHONE_INVALID` | 400 | Invalid phone number format |
| `FI_SCHEMA_RANGE_RATING` | 400 | Rating not between 1-5 |
| `FI_DATA_COUNTRY_INVALID` | 400 | Invalid country code |
| `TOO_MANY_REQUESTS` | 429 | Rate limit exceeded |

---

## TypeScript Support

The SDK includes full TypeScript definitions:

```typescript
import { Forminit } from 'forminit';

const forminit = new Forminit({ proxyUrl: '/api/forminit' });

const { data, error } = await forminit.submit('form-id', formData);

if (data) {
  console.log(data.hashId); // string
  console.log(data.date);   // string
  console.log(data.blocks); // object
}
```

---

## Rate Limits

| Authentication | Rate Limit |
|----------------|------------|
| With API Key | 5 requests per second per IP address |
| Without API Key | 1 request per 5 seconds per IP address |

---

## Best Practices

1. **Never expose API keys in client-side code.** Use a server-side proxy.
2. **Use FormData for file uploads.** JSON does not support file uploads.
3. **Always use the sender block** to identify form submitters.
4. **Handle errors gracefully.** Check for `error` in the response.
5. **Use E.164 format for phone numbers** (e.g., `+12025550123`).
6. **Use ISO 3166-1 alpha-2 codes for countries** (e.g., `US`, `GB`, `TR`).

---

## Resources

- [Form Blocks Reference](https://forminit.com/docs/form-blocks/)
- [File Uploads Guide](https://forminit.com/docs/file-upload/)
- [API Reference](https://forminit.com/docs/submit-form-api/)
