> ## Documentation Index
> Fetch the complete documentation index at: https://docs.webstorio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# App Data

> Define custom tables, manage rows, and expose data on your site via the API and SDK.

**App Data** lets you build custom database tables for your project — member directories, inventories, waitlists, resource libraries, or any structured data that does not fit the CMS or store.

Rows are validated against your schema. You control who can read or write via **API access presets** on each table.

**Available on:** Growth plan and above (10 tables / 5,000 rows on Growth; unlimited on Pro+).

## When to use App Data

| Use App Data when…                             | Use CMS instead when…                         |
| ---------------------------------------------- | --------------------------------------------- |
| You need typed columns and validation          | Content is editorial (blog, news, articles)   |
| Visitors submit or update structured records   | You publish entries with slugs and categories |
| You want a directory, catalog, or lookup table | Rich text and media are the main focus        |

| Use App Data when…                               | Use Forms instead when…                      |
| ------------------------------------------------ | -------------------------------------------- |
| You list, filter, and display many rows on pages | You only collect one-off submissions         |
| Rows are updated over time                       | You review submissions in a inbox-style list |

## Step 1 — Enable App Data

1. Open your **project dashboard**.
2. Go to **Features** and enable **App Data**.
3. Open **App Data** in the project sidebar.

You see an overview of **tables** and **total rows** for the project.

## Step 2 — Create a table

A **table** (data model) defines columns and rules for your data.

1. Go to **App Data → Tables**.
2. Click **Add table**.
3. Set a **name** and **key** (e.g. `team_directory`) — the key is used in the SDK and API.
4. Add **fields** with types:

| Field type              | Good for                |
| ----------------------- | ----------------------- |
| Short text              | Names, titles, codes    |
| Long text               | Descriptions, notes     |
| Number                  | Quantity, price, rating |
| Yes / no                | Flags, featured items   |
| Date                    | Deadlines, event dates  |
| Link / Email            | URLs, contact email     |
| Image                   | Photo URL               |
| Dropdown / Multi-select | Categories, tags        |
| JSON                    | Flexible nested data    |

5. Mark fields **required** or **unique** where needed.
6. Save the table.

## Step 3 — Add rows

1. Open **App Data → Rows** (or open a table and manage rows).
2. Click **Add row** and fill in field values.
3. Edit or delete rows from the dashboard anytime.

Validation runs on save — invalid types or missing required fields are rejected.

## Step 4 — Configure API access

Each table has **API access** settings that control how published pages and the SDK can use it. Operations are configured separately for **public** (anyone) and **authenticated** (signed-in) users.

Open the table → **API settings** and choose a preset:

| Group         | Preset                    | Who can access                                              |
| ------------- | ------------------------- | ----------------------------------------------------------- |
| **Private**   | No API access             | Dashboard only — hidden from the site API                   |
| **Signed-in** | Read only                 | Logged-in visitors can list and read all rows               |
|               | Own rows only             | Each signed-in user only sees and edits their own rows      |
|               | Read all, owner write     | Members can read all rows; only the owner can update/delete |
|               | Full access               | Any signed-in user can create, read, update, delete any row |
| **Public**    | Read only                 | Anyone can list and read via the site API                   |
|               | Read all, owner write     | Anyone reads; only the owner can update/delete              |
|               | Read all, signed-in write | Anyone reads; any signed-in user can write any row          |
|               | Full access               | Anyone can manage rows via the API                          |

<Warning>
  **Signed-in**, **owner write**, and **own rows** presets require [User Authentication](/guides/user-authentication). **Public write** exposes your table to the open internet — use only when you intend anonymous submissions.
</Warning>

You can also toggle individual operations under **Public API access** and **Authenticated API access**, plus **Read scope** (`All rows` vs `Own rows only`) and **Write scope** (`Any signed-in user` vs `Record owner only`) when those controls apply.

## Step 5 — Show data on your site

### Option A — Ask the AI (easiest)

In the page editor:

* *"Directory page listing all rows from my team\_directory table with name and role"*
* *"Detail page at `directory/{record_id}` showing one team member"*

The AI uses `window.webstorio.listRecords` and `getRecord` with your table key.

### Option B — SDK in page code

Editing page code yourself? Read and write rows with `window.webstorio` App Data methods (`listRecords`, `getRecord`, `createRecord`, and more), using your table key.

→ Methods, parameters, and examples: [App Data SDK reference](/api-reference/sdk/app-data)

## App Data vs CMS

|               | App Data                              | Content & CMS                      |
| ------------- | ------------------------------------- | ---------------------------------- |
| **Best for**  | Directories, inventories, app records | Blogs, articles, marketing content |
| **Structure** | Typed table columns                   | Flexible content type fields       |
| **URLs**      | Often custom page logic               | Slug-based entries, categories     |
| **Dashboard** | App Data → Tables / Rows              | Content → Types / Entries          |

## Plan limits

| Plan             | Tables    | Rows      |
| ---------------- | --------- | --------- |
| Free / Starter   | —         | —         |
| Growth           | 10        | 5,000     |
| Pro / Enterprise | Unlimited | Unlimited |

## Tips

<Tip>
  Start with **Public (read only)** while building pages, then tighten access before launch.
</Tip>

<Tip>
  Use **unique** on fields like email or slug when rows must not duplicate.
</Tip>

<Tip>
  Call `getDataModels()` in page code to discover table keys and schemas at runtime.
</Tip>

## For developers and agents

Page code uses `window.webstorio` App Data methods. → [App Data SDK](/api-reference/sdk/app-data)

Agents can create and update rows via [MCP](/developer/connect-mcp) (table schema still uses the dashboard UI).
