# ProofKit: fmdapi
> FileMaker Data API client (REST)
Documentation for the @proofkit/fmdapi package.
---
# Adapters
URL: https://proofkit.proof.sh/docs/fmdapi/adapters
Adapters are a new level of abstraction that allows you to reuse the same client API with any number of proxies, including via a FileMaker Webviewer using the [`@proofkit/webviewer`](/docs/webviewer/package) package and the Execute Data API script step. The adapter is responsible for handling the specifics of the connection to the FileMaker Data API, while the shared client exposes helper functions, schema validators, and other utilities to the developer.
Choose the adapter that is right for your project, or view below for how to build your own custom adatper.
OttoFMS (recommended) [#ottofms-recommended]
To connect via the [OttoFMS](https://docs.ottofms.com/) [Data API Proxy](https://docs.ottofms.com/ottofms-features/api-proxy#data-api-proxy), use the `OttoAdapter` with a Data API key:
```ts
import { DataApi, OttoAdapter } from "@proofkit/fmdapi";
```
The OttoAdapter is compatible with API keys for both the Otto v3 and OttoFMS Data API Proxy. OttoFMS is available under a free license and is our recommended method for interacting with the Data API.
Options [#options]
| Option | Type | Description |
| ------------- | -------- | ---------------------------------------------------------------------------------------- |
| `auth.apiKey` | `string` | The Data API key from either Otto v3 (starts with `KEY_`) or OttoFMS (starts with `dk_`) |
| `auth.port` | `string` | *(optional)* Only used for Otto v3. Defaults to 3030 |
| `db` | `string` | FileMaker database name |
| `server` | `string` | FileMaker server URL (must start with include `https://`) |
FetchAdapter [#fetchadapter]
To connect directly to the FileMaker Data API, use the `FetchAdapter` with a username and password:
```ts
import { DataApi, FetchAdapter } from "@proofkit/fmdapi";
```
Options [#options-1]
| Option | Type | Description |
| ------------ | ------------ | ------------------------------------------------------------------------------------------------------------------ |
| `auth` | `object` | Authentication object. Must contain `username` and `password` |
| `db` | `string` | FileMaker database name |
| `server` | `string` | FileMaker server URL (must include `https://`) |
| `tokenStore` | `TokenStore` | *(optional)* If provided, will use the custom set of functions to store and retrieve the short-lived access token. |
WebViewerAdapter [#webvieweradapter]
For rich webviewer experiences, use the `WebViewerAdapter` with the [`@proofkit/webviewer`](/docs/webviewer/package) package:
npm
pnpm
yarn
bun
```bash
npm install @proofkit/webviewer
```
```bash
pnpm add @proofkit/webviewer
```
```bash
yarn add @proofkit/webviewer
```
```bash
bun add @proofkit/webviewer
```
Then import the adapter like so:
```ts
import { DataApi } from "@proofkit/fmdapi";
import { WebViewerAdapter } from "@proofkit/webviewer";
```
Custom Adapters [#custom-adapters]
> **This is an advanced topic.** If you are just an application developer trying to connect to a FileMaker database, all you need to know is how you want to connect to the FileMaker server, then import the appropriate adapter. Type hint for the selected adapter will guide you through the rest.
If you want to write you own adapter for your own proxy, or to override the root-level `request` method, you can write a custom adapter.
All adapters must implement the `Adapter` interface. If you want to build a proxy similar to the `OttoAdapter`, you can extend the `BaseFetchAdapter` class and will likely only need to implement the `getToken` and `request` methods. View the source for the FetchAdapter for an example of this.
---
# Usage Examples
URL: https://proofkit.proof.sh/docs/fmdapi/examples
import { Callout } from "fumadocs-ui/components/callout";
import { Card, Cards } from "fumadocs-ui/components/card";
Prerequisites [#prerequisites]
Before you can use any of these methods, you need to set up a FileMaker Data API client. If you haven't done this yet, check out our [Quick Start Guide](/docs/fmdapi/quick-start) to create your client in a separate file.
For these examples, we'll assume you've already setup a client in another file and are importing it for use.
```ts
// This is just an example - follow the Quick Start guide for your actual setup
import { CustomersLayout } from "./schema/client";
```
***
Retrieving Data from FileMaker [#retrieving-data-from-filemaker]
Finding Records [#finding-records]
You can use the `find` method to perform FileMaker-style find requests on a layout. This method is limited to 100 records by default, but you can use the `findAll` helper method to automatically paginate the results and return all records that match the query.
```ts twoslash title="searchCustomers.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
// Simple search - find customers in a specific city (max 100 records)
export async function findCustomersByCity(city: string) {
const response = await CustomersLayout.find({
query: { city: city }
});
console.log(`Found ${response.data.length} customers in ${city}`);
return response.data;
}
// Get ALL matching records at once (handles pagination automatically)
export async function getAllActiveCustomers() {
const records = await CustomersLayout.findAll({
query: { status: "==Active" } // all standard FileMaker operators are supported
});
return records; // All active customers, no pagination needed
}
```
Use an array of find requests to get the OR behavior, equivalent to having multiple find requests in FileMaker.
```ts twoslash title="multipleFindRequests.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
export async function getCustomersByCityOrStatus(city: string, status: string) {
const records = await CustomersLayout.findAll({
query: [{ city }, { status }]
});
return records;
}
```
There are also helper methods for common find scenarios. Any of these methods will return just a single record instead of an array.
* `findOne` will throw an error unless there is exactly one record found
* `findFirst` will return the first record found, but still throw if no records are found
* `maybeFindFirst` will return the first record found or null
Getting All Records [#getting-all-records]
If you don't need to specify any find requests, you can use the `list` or `listAll` methods. `list` will limit to 100 records per request by default, while `listAll` will automatically handle pagination via the API and return all records for the entire table. Use with caution if the table is large!
```ts twoslash title="getAllCustomers.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
// Get a page of customers (recommended for large datasets)
export async function listCustomers() {
const response = await CustomersLayout.list({
sort: [{ fieldName: "firstName", sortOrder: "ascend" }]
});
return {
customers: response.data,
totalRecords: response.dataInfo.foundCount,
hasMore: response.data.length === 100 // Default page size
};
}
// Get ALL customers at once (use with caution on large datasets)
export async function listAllCustomers() {
const records = await CustomersLayout.listAll();
type CustomerRecord = (typeof records)[number];
console.log(`Retrieved all ${records.length} customers`);
return records.map((customer: CustomerRecord) => ({
id: customer.recordId,
firstName: customer.fieldData.firstName,
lastName: customer.fieldData.lastName,
email: customer.fieldData.email,
city: customer.fieldData.city
}));
}
```
***
Creating Records [#creating-records]
Use `create` to add new records to your FileMaker database.
```ts twoslash title="createCustomer.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
export async function createNewCustomer(customerData: {
firstName: string;
lastName: string;
email: string;
phone?: string;
city?: string;
}) {
const response = await CustomersLayout.create({
fieldData: {
firstName: customerData.firstName,
lastName: customerData.lastName,
email: customerData.email,
phone: customerData.phone || "",
city: customerData.city || "",
status: "Active",
created_date: new Date().toISOString()
}
});
console.log(`Created customer with ID: ${response.recordId}`);
return response.recordId;
}
```
***
Update / Delete Records [#update--delete-records]
Updating or deleting records requires the internal record id from FileMaker, not the primary key for your table. This value is returned in the `recordId` field of any create, list, or find response.
This record id *can* change during imports or data migrations, so you should never store it, but instead alwyas look it up via a find request when it's needed.
```ts twoslash title="updateCustomer.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
export async function updateCustomerInfo(myPrimaryKey: string, updates: {
firstName?: string;
lastName?: string;
phone?: string;
city?: string;
}) {
const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey: myPrimaryKey } });
// Only update fields that were provided
const fieldData: any = {};
if (updates.firstName) fieldData.firstName = updates.firstName;
if (updates.lastName) fieldData.lastName = updates.lastName;
if (updates.phone) fieldData.phone = updates.phone;
if (updates.city) fieldData.city = updates.city;
const response = await CustomersLayout.update({ fieldData, recordId });
return response.modId;
}
```
```ts twoslash title="deleteCustomer.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
export async function deleteCustomer(myPrimaryKey: string) {
// Optional: Get customer info first for logging
const { data: { recordId } } = await CustomersLayout.findOne({ query: { myPrimaryKey: myPrimaryKey } });
await CustomersLayout.delete({recordId});
}
```
***
Working with Scripts [#working-with-scripts]
FileMaker scripts can be executed during any other method or run directly.
Running Scripts Directly [#running-scripts-directly]
Use `executeScript` to run a script directly.
```ts twoslash title="executeScripts.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
export async function sendEmailFromFileMaker() {
const response = await CustomersLayout.executeScript({
script: "Send Email",
scriptParam: JSON.stringify({
to: "customer@example.com",
subject: "Welcome to our service",
body: "Thank you for signing up!"
})
});
console.log("Script result:", response.scriptResult);
return response.scriptResult;
}
```
Run a script with another method [#run-a-script-with-another-method]
You can run scripts before or after any data operation. The script will be run in the context of the layout specified in your client and will be on the record or found set as the operation. This is especially useful when creating records, as you can run a script after the record is created, knowing the script will be focused on this newly created record; thus giving you access to the calculated values such as a UUID primary key defined in your field definitions.
```ts twoslash title="scriptsWithOperations.ts"
import { CustomersLayout } from "./CustomersLayout";
// ---cut---
// Run a script after creating a record
export async function createCustomerWithWelcomeEmail(customerData: any) {
const response = await CustomersLayout.create({
fieldData: customerData,
script: "Send Welcome Email", // script name
// script param must always be a string
"script.param": JSON.stringify({
email: customerData.email,
name: `${customerData.firstName} ${customerData.lastName}`
})
});
return {
recordId: response.recordId,
scriptResult: response.scriptResult
};
}
```
For more details about the script execution order, see [this page](https://help.claris.com/en/data-api-guide/content/run-script-with-another-request.html) of the FileMaker Data API guide.
***
See also
Complete list of all available methods
Set up your FileMaker Data API client
---
# Overview
URL: https://proofkit.proof.sh/docs/fmdapi
@proofkit/fmdapi
This package is designed to make working with the FileMaker Data API much easier. Here's just a few key features:
For generated ProofKit Web Viewer apps, start with [Hybrid App Data Access](/docs/webviewer/data-access) to understand when this package is used directly and when FileMaker scripts are the better runtime path.
* Handles token refresh for you automatically
* [OttoFMS](https://ottofms.com/) Data API proxy support
* TypeScript support for easy auto-completion of your field names
* [Automated type generation](/docs/typegen) based on layout metadata
* Protection against field name changes with [Standard Schema](https://standardschema.dev/) runtime validation
* Supports both node and edge runtimes with a customizable token store
* Customizable adapters allow usage even within the [FileMaker Web Viewer](/docs/webviewer/package)
Edge Runtime Support [#edge-runtime-support]
This package is compatible with edge runtimes, but there are some additional considerations to avoid overwhelming your FileMaker server with too many connections. If you are developing for the edge, be sure to implement one of the following strategies:
* ✅ Use a custom token store (see above) with a persistent storage method such as Upstash
* ✅ Use a proxy such as the [Otto Data API Proxy](https://www.ottofms.com/docs/otto/working-with-otto/proxy-api-keys/data-api) which handles management of the access tokens itself.
* Providing an API key to the client instead of username/password will automatically use the Otto proxy
---
# Quick Start - Manual
URL: https://proofkit.proof.sh/docs/fmdapi/manual-setup
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Callout } from "fumadocs-ui/components/callout";
> Note: For the best experience, use the [@proofkit/typegen](/docs/typegen) tool to generate layout-specific clients and get autocomplete hints in your IDE with your actual field names. This minimal example just demonstrates the basic setup
Add the following envnironment variables to your project's `.env` file:
```sh
FM_DATABASE=filename.fmp12
FM_SERVER=https://filemaker.example.com
# if you want to use the OttoFMS Data API Proxy
OTTO_API_KEY=dk_123456...789
# otherwise
FM_USERNAME=admin
FM_PASSWORD=password
```
Initialize the client with credentials, depending on your adapter
```ts
// to use the OttoFMS Data API Proxy
import { DataApi, OttoAdapter } from "@proofkit/fmdapi";
const client = DataApi({
adapter: new OttoAdapter({
auth: { apiKey: process.env.OTTO_API_KEY },
db: process.env.FM_DATABASE,
server: process.env.FM_SERVER,
}),
layout: "API_Contacts",
});
```
```ts
// to use the raw Data API
import { DataApi, FetchAdapter } from "@proofkit/fmdapi";
const client = DataApi({
adapter: new FetchAdapter({
auth: {
username: process.env.FM_USERNAME,
password: process.env.FM_PASSWORD,
},
db: process.env.FM_DATABASE,
server: process.env.FM_SERVER,
}),
layout: "API_Contacts",
});
```
Then, use the client to query your FileMaker database. [View all available methods here](https://github.com/proofsh/fmdapi/wiki/methods).
Basic Example:
```typescript
const result = await client.list({ layout: "Contacts" });
```
TypeScript Support [#typescript-support]
If you define a schema in your client, the types will be inferred automatically. [Learn more](/docs/fmdapi/validation)
The basic client will return the generic FileMaker response object by default. You can also create a type for your expected response and get a fully typed response that includes your own fields.
```typescript
type TContact = {
name: string;
email: string;
phone: string;
};
// if you have portals
type TOrders = {
"Orders::orderId": string;
"Orders::orderDate": string;
"Orders::orderTotal": number;
};
type TPortals = {
orders: TOrders; // key is based on the portal object name
};
const client = DataApi({
layout: "API_Contacts",
// ... your adapter, other config
});
```
💡 TIP: For a more ergonomic TypeScript experience, use the [@proofkit/typegen tool](/docs/typegen) to generate these types based on your FileMaker layout metadata.
---
# Methods
URL: https://proofkit.proof.sh/docs/fmdapi/methods
The following methods are available for all adapters.
* `list` return all records from a given layout
* `find` perform a FileMaker find
* `get` return a single record by recordID
* `create` return a new record
* `update` modify a single record by recordID
* `delete` delete a single record by recordID
Helper Functions [#helper-functions]
This package also includes some helper methods to make working with Data API responses a little easier:
* `findOne` return the first record from a find instead of an array. This method will error unless exactly 1 record is found.
* `findFirst` return the first record from a find instead of an array, but will not error if multiple records are found.
* `findAll` return all found records from a find, automatically handling pagination. Use caution with large datasets!
* `listAll` return all records from a given layout, automatically handling pagination. Use caution with large datasets!
Adapter-Specific Functions [#adapter-specific-functions]
The first-party `FetchAdapter` and `OttoAdatper` both share the following additional methods from the `BaseFetchAdapter`:
* `executeScript` execute a FileMaker script directly
* `layoutMetadata` return metadata for a given layout
* `layouts` return a list of all layouts in the database (top-level layout key ignored)
* `scripts` return a list of all scripts in the database (top-level script key ignored)
* `globals` set global fields for the current session (top-level globals key ignored)
If you have your own proxy, you can write your own Custom Adapter that extends the BaseFetchAdapter to also implement these methods.
Fetch Adapter [#fetch-adapter]
* `disconnect` forcibly logout of your FileMaker session
Otto Adapter [#otto-adapter]
No additional methods
---
# Quick Start - Typegen
URL: https://proofkit.proof.sh/docs/fmdapi/quick-start
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Steps, Step } from "fumadocs-ui/components/steps";
import { AgentCommand } from "@/components/AgentCommand";
The typegen tool is the best way to interact with this library, as it will automatically generate layout-specific clients and get autocomplete hints in your IDE with your actual field names from your solution
Install the required packages [#install-the-required-packages]
npm
pnpm
yarn
bun
```bash
npm install @proofkit/fmdapi zod
```
```bash
pnpm add @proofkit/fmdapi zod
```
```bash
yarn add @proofkit/fmdapi zod
```
```bash
bun add @proofkit/fmdapi zod
```
Zod is used by the typegen tool by default, but it can be excluded if you set `validator` to `false` in the typegen config.
AI Agent Integration [#ai-agent-integration]
If you use an AI coding agent, run this command to map ProofKit's built-in skills to your project. See the [TanStack Intent docs](https://tanstack.com/intent/latest/docs/getting-started/quick-start-consumers) for more details.
Create a typegen config file in your project [#create-a-typegen-config-file-in-your-project]
```sh
npx @proofkit/typegen
```
Add the layouts you want to generate clients for to the `layouts` array in the config file.
```jsonc title='proofkit-typegen.config.jsonc'
{
"$schema": "https://proofkit.proof.sh/typegen-config-schema.json",
"config": {
"clientSuffix": "Layout",
"layouts": [
// add your layouts and name schemas here
{ "layoutName": "my_layout", "schemaName": "MySchema" }
// repeat as needed for each layout...
// { layoutName: "my_other_layout", schemaName: "MyOtherSchema" },
],
// change this value to generate the files in a different directory
"path": "schema",
"clearOldFiles": true
},
}
```
Setup Environment Variables [#setup-environment-variables]
Add the following envnironment variables to your project's `.env` file:
```bash title=".env"
FM_SERVER=https://filemaker.example.com # must start with https://
FM_DATABASE=filename.fmp12 # must end with .fmp12
# if you want to use the OttoFMS Data API Proxy (recommended)
OTTO_API_KEY=dk_123456...789
# otherwise
FM_USERNAME=admin
FM_PASSWORD=password
```
Generate the layout-specific clients [#generate-the-layout-specific-clients]
Run this command any time you make changes to your config file, any of the referenced FileMaker layouts, or any field names/types that are on the layouts.
```sh
npx @proofkit/typegen
```
Tip: Add a script to your `package.json` to make it easier to run in the future.
```jsonc title="package.json"
{
"scripts": {
// ...
"typegen": "npx @proofkit/typegen"
}
}
```
Usage [#usage]
You can now import the layout-specifc client for use in your project.
```ts title="getCustomer.ts"
import { CustomersLayout } from "./schema/client";
export async function getCustomer(id: string) {
// findOne will throw an error unless exactly 1 record is returned
const { data } = await CustomersLayout.findOne({
query: {
id: `==${id}`
}
});
return data.fieldData;
}
```
For all available methods, see
[this page](/docs/fmdapi/methods)
.
Customization [#customization]
If you run into any limitations from the generated code, there are many ways to customize it to your needs.
How to configure the typegen tool for your use case.
Customize the shape of the data returned from your database.
---
# Token Store
URL: https://proofkit.proof.sh/docs/fmdapi/token-store
This page applies only to the FetchAdapter when your connecting via username/password to your FileMaker server. The Otto Data API Proxy manages the token for you.
If you are using username/password authentication, the fmdapi client will manage your access token for you. By default, the token is kept in memory only, but you can provide other getter and setter methods to store the token in a database or other location. Included in this package are helper functions for file storage if you have access to the filesystem, or Upstash if running in a serverless environment.
```ts
import { DataApi, FetchAdapter } from "@proofkit/fmdapi";
// using file storage, if you have persistent access to the filesystem on your server
import { fileTokenStore } from "@proofkit/fmdapi/tokenStore/file";
const client = DataApi({
adapter: new FetchAdapter({
// ...
tokenStore: fileTokenStore(),
}),
});
// or with Upstash, requires `@upstash/redis` as peer dependency
import { upstashTokenStore } from "@proofkit/fmdapi/tokenStore/upstash";
const client = DataApi({
adapter: new FetchAdapter({
// ...
tokenStore: upstashTokenStore({
token: process.env.UPSTASH_TOKEN,
url: process.env.UPSTASH_URL,
}),
}),
});
```
---
# Validation & Transformation
URL: https://proofkit.proof.sh/docs/fmdapi/validation
Protect your app from field name changes by validating the shape of the data returned from the FileMaker Data API.
import { File, Folder, Files } from "fumadocs-ui/components/files";
import { IconFileTypeTs } from "@tabler/icons-react";
Why validate? [#why-validate]
One of the best features of the FileMaker platform is how you can easily add, remove, and rename fields in your database. However, when you make integrations that are beyond the scope of your database, you can run into serious issues if the field names change out from under you.
This library supports validation using [Standard Schema](https://standardschema.dev/) out of the box, and will throw an error *early* to prevent unexpected behavior in your app. We suggest using the [Zod](https://zod.dev) library by default, but any other validation library that supports Standard Schema will also work.
How does it work? [#how-does-it-work]
When creating your layout client, add a `schema` property and define a Standard-Schema compliant schema definition for your `fieldData` and `portalData`. Your schema must be an object, and should represent a single record or portal row.
Most validation libraries also support some kind of transformation, and you can use these to adjust how your FileMaker data is returned to your app.
Try this interactive example that uses the [Zod](https://zod.dev/) library to validate and transform the data:
Handling errors [#handling-errors]
If you define a schema, each method that you call may cause the API request to throw a validation error, thus no data returned to your application (even if the FileMaker Server gave an OK status code). You should always try/catch these methods and update your schemas when your field names change. The easiest way to keep your schemas up to date is with the [@proofkit/typegen](/docs/typegen) package.
Typegen Integration [#typegen-integration]
If you use [@proofkit/typegen](/docs/typegen) to generate the layout-specific clients, it will automatically generate zod validators also.
These generated files should **never** be edited, since your changes would just be overwritten the next time you run an update to your schema. However, you can and should add overrides to the files at the root of your schemas, as only the files in the `client` and `generated` folders will be overwritten.
---
# Upgrading to v5
URL: https://proofkit.proof.sh/docs/fmdapi/version-5
import { Callout } from "fumadocs-ui/components/callout";
In v5, we've split the Data API and typegen functionality into two separate packages: `@proofkit/fmdapi` and `@proofkit/typegen`, as well as introduces a few breaking changes.
Codemod [#codemod]
To make the transition as smooth as possible, we've made an upgrade script to the `@proofgeist/fmdapi`
package. Simply run this command in the root of your project:
```bash
npx @proofgeist/fmdapi@latest upgrade
```
This script will:
* Install the new packages (@proofkit/fmdapi and @proofkit/typegen)
* Remove the old package (@proofgeist/fmdapi)
* Migrate your existing config file to the new format
* Attempt to re-run the typegen command to generate new clients
After running the command, you'll likely want to run `tsc` to check for any issues. You may need to simply do a full project find/replace for `@proofgeist/fmdapi` and replace with `@proofkit/fmdapi`.
We also suggest creating/updating the "typegen" script in your `package.json` file to use the new `@proofkit/typegen` package.
```json
"typegen": "npx @proofkit/typegen"
```
What's new? [#whats-new]
Validation / Transformations [#validation--transformations]
Zod is no longer required as a peer dependency, and you can now use any library that supports [Standard Schema](https://standardschema.dev/) as your runtime validator. Zod will still be used by the typegen package by default, but only if you want to use it in your runtime application.
Each method called will now also return the result of your validator, so you can define custom transformations if supported by your validation library.
Here's an example of how you might use zod to force a number field to a boolean, or a string to a JavaScript Date:
```ts title="schema/Customers.ts"
import { z } from "zod/v4";
import { ZCustomers as ZCustomers_generated } from "./generated/Customers";
import dayjs from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
dayjs.extend(customParseFormat);
export const ZCustomers = ZCustomers_generated.omit({ active: true }).extend({
active: z.coerce.boolean(),
createdAt: z
.string()
.transform((v) => dayjs(v, ["MM/DD/YYYY"]))
.toDate(),
});
```
```ts title="index.ts"
import { CustomersLayout } from "./schema/client";
const { data } = await CustomersLayout.list();
data[0].fieldData.active; // --> boolean
```
Typegen [#typegen]
The typegen features have been isolated from the Data API package and are now available as a separate package: `@proofkit/typegen`. The typegen can be run exclusively with npx so you don't even need to install it as a dev dependency. This should make the package size even smaller and more focused on its core functionality.
Additionally, the generated code now allows you to specify overrides for each schema. Only the files in the `client` and `generated` folders will be overwritten, allowing you to write custom schemas or transformers in the files in the root of the generated folder.
Breaking Changes [#breaking-changes]
Layout-specific clients only [#layout-specific-clients-only]
Due to the change in how the runtime validators are now processed, it's now **required** to pass a layout name when initializing a client, and you can no longer override the layout per method. If you were exclusvily using generated clients from the typegen features, this should not affect you.
Token Store removed from typegen [#token-store-removed-from-typegen]
This was deprecated in v4 and is now removed **from typegen only**. You can still use a custom token store, but you will need to modify the typegen options and set `generateClient` to `false` so that you can use the generated types and/or validators, but create your own clients with your own token store for the Fetch adapter.
Typegen config updates [#typegen-config-updates]
For full details about the new typegen package, please see the [Typegen docs](/docs/typegen).
* Within the root config:
* `schemas` has been renamed to `layouts`
* `useZod` has been removed
* New option: `validator` can be set to `zod` or `false`
* Within the `layouts` config:
* `layout` has been renamed to `layoutName`