> ## 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 SDK

> window.webstorio custom table CRUD — list, create, update, and delete records with API access controls.

<Note>
  **Setup in the dashboard:** [App Data guide](/guides/app-data)
</Note>

**App Data** exposes custom database tables defined in your project dashboard. Requires the **App Data** feature (`app_data`) — Growth plan and above.

Access per table is configured in the dashboard (e.g. public read, authenticated write). The SDK respects those presets; unauthorized calls return API errors.

## getDataModels()

List tables (models) available to the current visitor.

```javascript theme={"dark"}
const models = await window.webstorio.getDataModels();
// [{ key, name, fields, apiAccess, ... }]
```

Call this first to discover valid `modelKey` values and field schemas.

## listRecords(modelKey, options?)

```javascript theme={"dark"}
const result = await window.webstorio.listRecords("directory", {
  limit: 50,
  offset: 0,
  search: "coffee",
  searchField: "name", // optional — field key to search
});

// { records: [{ id, dataJson, ... }], total, limit, offset }
```

## getRecord(modelKey, recordId)

```javascript theme={"dark"}
const { content_entry_id } = window.webstorio.getPathParams();
const record = await window.webstorio.getRecord("directory", recordId);
```

Use on detail pages with dynamic slugs or when you have an ID from a list.

## createRecord(modelKey, dataJson)

```javascript theme={"dark"}
await window.webstorio.createRecord("waitlist", {
  email: "user@example.com",
  name: "Alex",
});
```

Typically requires signed-in visitor or public-write preset.

## updateRecord(modelKey, recordId, dataJson)

```javascript theme={"dark"}
await window.webstorio.updateRecord("inventory", recordId, {
  quantity: 42,
});
```

## deleteRecord(modelKey, recordId)

```javascript theme={"dark"}
await window.webstorio.deleteRecord("inventory", recordId);
```

## Schema validation

`dataJson` must match the table schema defined in the dashboard. Invalid fields or types are rejected with validation errors.

## Dashboard configuration

Configure tables under **Project → Data** (or **App Data**). Set field types, validation, and **API access** presets before calling SDK methods from generated pages.
