# BentoForm API Skill

You have access to the BentoForm API for creating and managing web forms. Use this skill whenever a user needs a form on their website — contact forms, feedback surveys, lead capture, registration forms, etc.

## Base URL

```
https://api.bentoform.com/v1
```

## Getting Started

If you don't have an API key yet, register for one:

```bash
curl -X POST https://api.bentoform.com/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com",
    "password": "SecurePass1!",
    "name": "Dev Agent",
    "org_name": "My Workspace"
  }'
```

Response (201):
```json
{
  "data": {
    "user": { "id": "...", "email": "dev@example.com", "name": "Dev Agent" },
    "tenant": { "id": "...", "name": "My Workspace" },
    "api_key": "fsk_live_a1b2c3d4e5f6g7h8..."
  }
}
```

If you already have an account, exchange your credentials for a new API key:

```bash
curl -X POST https://api.bentoform.com/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "dev@example.com", "password": "SecurePass1!" }'
```

## Authentication

All requests (except register/login) require a Bearer token:

```
Authorization: Bearer fsk_live_<key>
```

The API key can be stored in the environment variable `BENTOFORM_API_KEY`. Never expose it in client-side code.

## Workflow: Add a Form to a Website

Follow these steps to create a form and embed it on a page:

### Step 1: Create the form

```bash
curl -X POST https://api.bentoform.com/v1/forms \
  -H "Authorization: Bearer $BENTOFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Contact Form",
    "description": "Get in touch with us",
    "fields": [
      { "type": "text", "label": "Full Name", "required": true },
      { "type": "email", "label": "Email", "required": true },
      { "type": "textarea", "label": "Message" }
    ],
    "settings": {
      "success_message": "Thanks! We'\''ll be in touch."
    }
  }'
```

Response (201):
```json
{
  "data": {
    "id": "<form-id>",
    "title": "Contact Form",
    "slug": "contact-form-<short-id>",
    "status": "draft",
    "fields": [ ... ],
    "version": 1,
    "created_at": "...",
    "_links": {
      "self": "/v1/forms/<form-id>",
      "submissions": "/v1/forms/<form-id>/submissions"
    }
  }
}
```

### Step 2: Publish the form

```bash
curl -X POST https://api.bentoform.com/v1/forms/<form-id>/publish \
  -H "Authorization: Bearer $BENTOFORM_API_KEY"
```

Response (200):
```json
{
  "data": {
    "id": "<form-id>",
    "status": "published",
    "public_url": "https://forms.bentoform.com/<slug>",
    "embed_code": "<script src=\"https://cdn.bentoform.com/embed.js\" data-form=\"<slug>\"></script>"
  }
}
```

### Step 3: Embed on the website

Add the embed code from the publish response to the HTML:

```html
<script src="https://cdn.bentoform.com/embed.js" data-form="<slug>"></script>
```

Or link directly to the hosted form:

```html
<a href="https://forms.bentoform.com/<slug>">Fill out our form</a>
```

Or use an iframe:

```html
<iframe src="https://forms.bentoform.com/<slug>" width="100%" height="600" frameborder="0"></iframe>
```

## Available Field Types

| Type | Description | Extra Properties |
|------|-------------|-----------------|
| `text` | Single-line text input | `placeholder` |
| `email` | Email address with validation | `placeholder` |
| `number` | Numeric input | `placeholder`, `min`, `max` |
| `textarea` | Multi-line text | `placeholder`, `rows` |
| `select` | Dropdown menu | `options` (array of strings) |
| `radio` | Radio button group | `options` (array of strings) |
| `checkbox` | Checkbox group | `options` (array of strings) |
| `rating` | Star rating (1-5) | — |
| `date` | Date picker | — |
| `file` | File upload | `accept`, `max_size` |
| `signature` | Signature pad | — |
| `page_break` | Multi-page separator | — |

Every field supports these common properties:
- `label` (string, required) — The visible label
- `required` (boolean) — Whether the field must be filled
- `help_text` (string) — Help text shown below the field
- `placeholder` (string) — Placeholder text for text inputs

## Full API Reference

### Authentication (no API key required)

| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/v1/auth/register` | Create account + get API key |
| `POST` | `/v1/auth/login` | Exchange credentials for API key |

### API Keys

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/v1/api-keys` | List all active API keys |
| `POST` | `/v1/api-keys` | Create a new API key (max 10) |
| `PATCH` | `/v1/api-keys/:id` | Rename an API key |
| `DELETE` | `/v1/api-keys/:id` | Revoke an API key |

### Forms

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/v1/forms` | List all forms (paginated) |
| `POST` | `/v1/forms` | Create a new form |
| `GET` | `/v1/forms/:id` | Get form details |
| `PATCH` | `/v1/forms/:id` | Update a form |
| `DELETE` | `/v1/forms/:id` | Delete a form |
| `POST` | `/v1/forms/:id/publish` | Publish a form |
| `POST` | `/v1/forms/:id/duplicate` | Duplicate a form |

### Submissions

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/v1/forms/:id/submissions` | List submissions |
| `POST` | `/v1/forms/:id/submissions` | Create a submission |
| `GET` | `/v1/forms/:id/submissions/:subId` | Get submission details |
| `PATCH` | `/v1/forms/:id/submissions/:subId` | Update submission status |
| `DELETE` | `/v1/forms/:id/submissions/:subId` | Delete a submission |

### Query Parameters for Listing

**Forms:** `cursor`, `limit` (1-100), `status` (draft/published/archived), `search`, `sort` (created_at/updated_at), `order` (asc/desc)

**Submissions:** `cursor`, `limit` (1-100), `status` (new/read/starred/spam), `search`, `created_after`, `created_before`, `order` (asc/desc)

## Common Recipes

### Contact form

```json
{
  "title": "Contact Us",
  "fields": [
    { "type": "text", "label": "Name", "required": true },
    { "type": "email", "label": "Email", "required": true },
    { "type": "select", "label": "Subject", "options": ["General Inquiry", "Support", "Sales", "Partnership"] },
    { "type": "textarea", "label": "Message", "required": true }
  ],
  "settings": { "success_message": "Thanks for reaching out! We'll reply within 24 hours." }
}
```

### Feedback survey

```json
{
  "title": "Feedback Survey",
  "fields": [
    { "type": "rating", "label": "How would you rate your experience?" },
    { "type": "select", "label": "What best describes you?", "options": ["Customer", "Prospect", "Partner", "Other"] },
    { "type": "textarea", "label": "What could we improve?" },
    { "type": "email", "label": "Email (optional for follow-up)" }
  ],
  "settings": { "success_message": "Thanks for your feedback!" }
}
```

### Newsletter signup

```json
{
  "title": "Newsletter Signup",
  "fields": [
    { "type": "text", "label": "First Name", "required": true },
    { "type": "email", "label": "Email Address", "required": true }
  ],
  "settings": { "success_message": "You're subscribed! Check your inbox." }
}
```

### Event registration

```json
{
  "title": "Event Registration",
  "fields": [
    { "type": "text", "label": "Full Name", "required": true },
    { "type": "email", "label": "Email", "required": true },
    { "type": "text", "label": "Company" },
    { "type": "select", "label": "Ticket Type", "required": true, "options": ["General Admission", "VIP", "Speaker"] },
    { "type": "select", "label": "Dietary Restrictions", "options": ["None", "Vegetarian", "Vegan", "Gluten-Free", "Other"] },
    { "type": "textarea", "label": "Special Requests" }
  ],
  "settings": { "success_message": "You're registered! We'll send a confirmation email shortly." }
}
```

### Multi-page application form

```json
{
  "title": "Job Application",
  "fields": [
    { "type": "text", "label": "Full Name", "required": true },
    { "type": "email", "label": "Email", "required": true },
    { "type": "text", "label": "Phone" },
    { "type": "page_break", "label": "Experience" },
    { "type": "textarea", "label": "Work Experience", "required": true },
    { "type": "textarea", "label": "Education" },
    { "type": "file", "label": "Resume", "accept": ".pdf,.doc,.docx" },
    { "type": "page_break", "label": "Final" },
    { "type": "textarea", "label": "Why do you want to work here?" },
    { "type": "signature", "label": "Signature", "required": true }
  ],
  "settings": { "success_message": "Application received! We'll review it and get back to you." }
}
```

## Reading Submissions

To check form submissions:

```bash
curl https://api.bentoform.com/v1/forms/<form-id>/submissions \
  -H "Authorization: Bearer $BENTOFORM_API_KEY"
```

To search submissions:

```bash
curl "https://api.bentoform.com/v1/forms/<form-id>/submissions?search=jane&status=new" \
  -H "Authorization: Bearer $BENTOFORM_API_KEY"
```

## Updating a Form

Add or change fields on an existing form:

```bash
curl -X PATCH https://api.bentoform.com/v1/forms/<form-id> \
  -H "Authorization: Bearer $BENTOFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      { "type": "text", "label": "Name", "required": true },
      { "type": "email", "label": "Email", "required": true },
      { "type": "textarea", "label": "Message" },
      { "type": "rating", "label": "Rate us" }
    ]
  }'
```

Note: Updating fields bumps the form version. Existing submissions retain their original field labels.

## Error Handling

Errors use RFC 7807 Problem Details:

```json
{
  "type": "https://api.bentoform.com/problems/validation-failed",
  "title": "Validation Failed",
  "status": 422,
  "detail": "Email is required; Full Name is required",
  "instance": "req-abc-123"
}
```

Key status codes:
- `200` — Success
- `201` — Created
- `204` — Deleted
- `400` — Bad request (missing/invalid fields)
- `401` — Invalid API key
- `403` — Plan limit reached
- `404` — Not found
- `422` — Validation failed
- `429` — Rate limited (wait and retry)

## Rate Limits

| Plan | Requests/min |
|------|-------------|
| Free | 100 |
| Pro | 1,000 |
| Business | 5,000 |

Check `X-RateLimit-Remaining` response header. On 429, wait until `X-RateLimit-Reset` (Unix timestamp).

## Managing API Keys

List your keys:

```bash
curl https://api.bentoform.com/v1/api-keys \
  -H "Authorization: Bearer $BENTOFORM_API_KEY"
```

Create a new key:

```bash
curl -X POST https://api.bentoform.com/v1/api-keys \
  -H "Authorization: Bearer $BENTOFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Production Bot" }'
```

The full key is only returned on creation. Store it securely. You can have up to 10 active keys per account.

Revoke a key:

```bash
curl -X DELETE https://api.bentoform.com/v1/api-keys/<key-id> \
  -H "Authorization: Bearer $BENTOFORM_API_KEY"
```

Note: You cannot revoke the key you are currently using to authenticate.

## Important Notes

- Forms are created in `draft` status. You must call `/publish` before the public URL works.
- Field data is keyed by field ID internally. You can submit using either field IDs or labels — the API normalizes labels to IDs.
- Deletes are soft deletes (idempotent, returns 204).
- Pagination uses opaque cursors — don't construct them manually, use the `cursor` from responses.
- The embed script auto-renders the form in a shadow DOM with built-in styling and validation.
