Dyrected
Deliver ContentTyped SDK

Overview

The typed SDK is the fastest way to read and write Dyrected content from JavaScript and TypeScript.

The Dyrected SDK (@dyrected/sdk) is a small typed client for talking to your Dyrected API. It gives you fully typed collection and global access, query building, uploads, and workflow transitions without hand-writing fetch calls.

If you are working in JavaScript or TypeScript, reach for the SDK first. Drop down to the REST API only when you need a language the SDK does not cover.

Creating a client

Create one client and reuse it. Point it at the origin of your Dyrected app — the SDK adds the /api prefix itself.

There are two normal ways to type that client:

  • use InferSchema when the app can import exported collection and global constants directly from dyrected.config.ts
  • use generated DyrectedSchema when the app should read from dyrected-types.ts instead of importing schema code

If you already generated dyrected-types.ts, you do not need to infer the schema again by hand. Use DyrectedSchema directly:

import { createClient } from "@dyrected/sdk";
import type { DyrectedSchema } from "./dyrected-types";

const client = createClient<DyrectedSchema>({
  baseUrl: "https://example.com",
  apiKey: process.env.DYRECTED_API_KEY,
});

const { docs: posts } = await client.collection("posts").find({
  where: { status: { equals: "published" } },
  sort: "-createdAt",
  depth: 1,
});

Because the client is generic over your schema, find, create, and update return typed documents and reject unknown fields at compile time.

If your app and schema live in the same codebase and you prefer not to generate a file, the TypeScript docs show the InferSchema path in TypeScript Overview and InferSchema.

What you can do

  • Read and write collections through client.collection('slug').
  • Read and update singletons through client.global('slug').
  • Shape reads with sort, filter, depth, pagination, and free-text search.
  • Compute fast statistics and counts with aggregate.
  • Upload files and run workflow transitions on documents that support them.

For example, collection search is now first-class in the SDK:

const { docs } = await client.collection("posts").find({
  search: "grace hopper",
  where: { status: { equals: "published" } },
})

Use search when you want the collection's configured backend search behavior. The server merges it with your where clause using AND, so free-text search and structured filters work together.

Managing media & folders

Organize upload collections, manipulate folders, and replace asset files in-place:

// 1. Create a media folder
const folder = await client.createFolder("media", {
  name: "Summer Campaign",
  color: "#3b82f6",
});

// 2. List all folders in a collection
const { docs: folders } = await client.listFolders("media");

// 3. Upload a file directly into a folder
const asset = await client.collection("media").upload(myFile, {
  folderId: folder.id,
  alt: "Summer campaign banner",
});

// 4. Replace an existing file in-place (keeps the same document ID)
const updatedAsset = await client.replaceMedia(asset.id, newFile);

// 5. Delete multiple assets in batch
await client.deleteMany("media", {
  ids: ["asset-1", "asset-2"],
});

Managing authentication & invitations

When a collection has auth: true or an auth config, client.collection(slug) exposes full auth lifecycle methods:

// 1. Invite a user with initial role data and custom action URL
const invite = await client.collection("users").invite("[email protected]", {
  inviteUrl: "https://myapp.com/accept-invite",
  data: { roles: ["editor"], name: "Alex" },
});
console.log(`Invite sent: ${invite.emailSent}, token: ${invite.token}`);

// 2. Mint a headless invite token without sending an email (for SMS, custom delivery)
const headless = await client.collection("users").createInviteToken({
  email: "[email protected]",
  inviteUrl: "https://myapp.com/onboarding",
});

// 3. Verify an invite or reset token when your frontend component mounts
const check = await client.collection("users").verifyToken(tokenFromUrl, "invite");
if (check.valid) {
  console.log(`Token verified for ${check.email}`);
} else {
  console.error(`Token invalid or expired: ${check.error}`);
}

// 4. Complete invite acceptance with a user-chosen password
const { token, user } = await client.collection("users").acceptInvite(
  tokenFromUrl,
  "secure-password-123",
  { department: "Design" },
);
client.setToken(token);

// 5. Send a password reset or mint a headless reset token
await client.collection("users").sendPasswordReset("[email protected]", {
  resetUrl: "https://myapp.com/reset-password",
});
const resetToken = await client.collection("users").createPasswordResetToken("[email protected]");

For the endpoint-by-endpoint details and server behavior, read Authentication Operations.

Handling errors

SDK calls throw a typed DyrectedError when the API returns a non-success status, so you can branch on status codes and surface server validation messages safely.

Generated reference

The contracts below are generated from the public @dyrected/sdk exports by @dyrected/knowledge, so the client, factory, options, and error types stay in sync with the package. Query-shaping details live on the sort, filter, depth, and pagination pages.

AuditEntry

A single audit entry returned by client.audit() or client.collection(slug).audit().

export interface AuditEntry {
  id: string;
  collection: string;
  documentId: string | null;
  operation: string;
  user: string | null;
  timestamp: string;
  changes?: string | Record<string, unknown> | null;
}
OptionDescription
id (required)
collection (required)
documentId (required)
operation (required)
user (required)
timestamp (required)
changes (optional)

BaseSchema

Exported interface from @dyrected/sdk.

export interface BaseSchema {
  collections: Record<string, UnknownRecord>;
  globals: Record<string, UnknownRecord>;
}
OptionDescription
collections (required)
globals (required)

createClient

Exported function from @dyrected/sdk.

export function createClient<TSchema extends SchemaShape = RegisteredSchema>(
  config: DyrectedClientConfig,
): DyrectedClient<TSchema>

DyrectedClient

Exported class from @dyrected/sdk.

export class DyrectedClient<TSchema extends SchemaShape = RegisteredSchema> {
}
OptionDescription
setToken (required)Update the Authorization header with a Bearer token. Call this after a successful login.
clearToken (required)Remove the Authorization header. Call this after logout.
getAuthHeaders (required)Returns the headers needed to authenticate raw `fetch()` calls made outside the SDK client (e.g. streaming endpoints, dynamic options). Includes the Authorization bearer token (if set), x-api-key, and x-site-id.
getBaseUrl (required)
getSchemas (required)
getAdminAuthConfig (required)
exchangeAdminAuth (required)
getPreference (optional)
setPreference (optional)
deletePreference (optional)
getNavigation (required)Fetches the dynamic runtime navigation tree compiled for the current user.
getNavigationBadges (optional)Fetches real-time badge counts and status for navigation items.
getPreviewData (required)Fetch draft data for a specific preview token. Used in "token" preview mode.
createPreviewToken (optional)Mint a short-lived preview token that carries the current (unsaved) draft data. Used by the Admin in `previewMode: "token"` to hand draft content to a server-rendered frontend that cannot receive it over `postMessage`. Requires an authenticated request (the Admin is logged in).
ai (optional)AI Assistant methods for managing threads, messaging, human-in-the-loop action approvals, semantic RAG search, and AI chat.
find (required)
collection (required)Returns a fluent query builder for a collection.
global (required)Access a global by its slug with a fluent builder.
trash (optional)Access trash operations, either collection-scoped or globally.
findOne (optional)
create (required)
update (required)
delete (optional)
transition (required)Perform a workflow transition on a document. Sends `POST /api/collections/:collection/:id/transitions/:transition`. Requires the client to have a valid bearer token set via `setToken()`.
workflowHistory (optional)Fetch the workflow history for a document. Sends `GET /api/collections/:collection/:id/workflow-history`.
audit (required)Fetch audit entries across every audited collection the current caller can read. Sends `GET /api/audit`.
collectionAudit (required)Fetch audit entries for a single collection. Sends `GET /api/collections/:collection/__audit`.
deleteMany (optional)
getGlobal (optional)
updateGlobal (required)
listMedia (required)
listFolders (required)List all media folders in an upload-enabled collection.
createFolder (optional)Create a new media folder in an upload-enabled collection.
updateFolder (optional)Update an existing media folder in an upload-enabled collection.
deleteFolder (required)Delete a media folder from an upload-enabled collection.
uploadMedia (required)
replaceMedia (required)Replace the underlying file of an existing media document in-place without creating a duplicate record.
deleteMedia (required)

DyrectedClientConfig

Exported interface from @dyrected/sdk.

export interface DyrectedClientConfig {
  baseUrl: string;
  apiKey?: string;
  siteId?: string;
  headers?: Record<string, string>;
  fetch?: typeof fetch;
  /**
   * Callback invoked when a 401 Unauthorized response is returned from an authenticated endpoint.
   */
  onAuthError?: (error: DyrectedError) => void;
  /**
   * Default relationship population depth applied to document reads
   * (`find`, `findOne`, `global().get()`, and media listing) when a call
   * does not pass its own `depth`. Defaults to `1`.
   */
  defaultDepth?: number;
}
OptionDescription
baseUrl (required)
apiKey (optional)
siteId (optional)
headers (optional)
fetch (optional)
onAuthError (optional)Callback invoked when a 401 Unauthorized response is returned from an authenticated endpoint.
defaultDepth (optional)Default relationship population depth applied to document reads (`find`, `findOne`, `global().get()`, and media listing) when a call does not pass its own `depth`. Defaults to `1`.

DyrectedError

Structured error thrown by the SDK when the server returns a non-2xx response.

export class DyrectedError extends Error {
}
OptionDescription
statusCode (required)
errors (optional)

getPreviewToken

Extract the preview token from a request's query string. Accepts a raw query string, a URLSearchParams, or a plain params object (e.g. Nuxt's route.query or Next's searchParams). Returns null when absent.

export function getPreviewToken(
  search: string | URLSearchParams | Record<string, unknown> | undefined | null,
): string | null

InferSchema

Derives a typed TSchema from your exported collection and global config constants.

Pass it to createClient<Schema>() so every find, findOne, create, update, global().get() call returns the inferred document shape — no manual interfaces required.

export type InferSchema<
  TCollections extends Record<string, CollectionConfig<UnknownRecord>>,
  TGlobals extends Record<string, GlobalConfig<UnknownRecord>> = Record<
    never,
    never
  >,
> = {
  collections: { [K in keyof TCollections]: ExtractDoc<TCollections[K]> };
  globals: { [K in keyof TGlobals]: ExtractDoc<TGlobals[K]> };
};

InviteOptions

Exported interface from @dyrected/sdk.

export interface InviteOptions {
  inviteUrl?: string;
  sendEmail?: boolean;
  data?: UnknownRecord;
  [key: string]: unknown;
}
OptionDescription
inviteUrl (optional)
sendEmail (optional)
data (optional)

InviteResult

Exported interface from @dyrected/sdk.

export interface InviteResult {
  success: boolean;
  message: string;
  token: string;
  inviteUrl: string;
  emailSent: boolean;
  emailError?: string;
}
OptionDescription
success (required)
message (required)
token (required)
inviteUrl (required)
emailSent (required)
emailError (optional)

MediaFolder

Shape of a media folder document in the DAM system.

export interface MediaFolder {
  id: string;
  name: string;
  slug: string;
  collection: string;
  parentId: string | null;
  path: string;
  color?: string | null;
  createdAt?: string;
  updatedAt?: string;
}
OptionDescription
id (required)
name (required)
slug (required)
collection (required)
parentId (required)
path (required)
color (optional)
createdAt (optional)
updatedAt (optional)

PasswordResetOptions

Exported interface from @dyrected/sdk.

export interface PasswordResetOptions {
  resetUrl?: string;
  sendEmail?: boolean;
}
OptionDescription
resetUrl (optional)
sendEmail (optional)

PasswordResetResult

Exported interface from @dyrected/sdk.

export interface PasswordResetResult {
  success: boolean;
  message: string;
  emailSent: boolean;
  emailError?: string;
  token?: string;
  resetUrl?: string;
}
OptionDescription
success (required)
message (required)
emailSent (required)
emailError (optional)
token (optional)
resetUrl (optional)

PREVIEW_TOKEN_PARAM

The query-string parameter the Admin appends to a preview URL in previewMode: "token". Read it on your frontend to decide whether to fetch draft data instead of published content.

export const PREVIEW_TOKEN_PARAM = "dyPreview";

Register

Exported interface from @dyrected/sdk.

export interface Register {}

RegisteredComponentKeys

Component keys registered via CLI type generation on Register['componentKeys']. Falls back to loose string records when types have not been generated.

export type RegisteredComponentKeys = Register extends { componentKeys: infer K }
  ? K
  : {
      fields?: string;
      dashboard?: string;
      collectionList?: string;
      collectionView?: string;
      forms?: string;
      viewLayouts?: string;
      pages?: string;
      customComponents?: string;
    };

RegisteredSchema

Exported type from @dyrected/sdk.

export type RegisteredSchema = Register extends { schema: infer S }
  ? S extends SchemaShape
    ? S
    : BaseSchema
  : BaseSchema;

RunActionArgs

Arguments accepted by client.collection(slug).runAction().

export interface RunActionArgs {
  /** Target a single document (row action). */
  id?: string;
  /** Target multiple documents (bulk action). */
  ids?: string[];
  /** Values collected from the action's input form dialog. */
  input?: Record<string, unknown>;
}
OptionDescription
id (optional)Target a single document (row action).
ids (optional)Target multiple documents (bulk action).
input (optional)Values collected from the action's input form dialog.

SchemaResponse

Exported interface from @dyrected/sdk.

export interface SchemaResponse {
  blocks?: Block[];
  collections: CollectionConfig[];
  globals: GlobalConfig[];
  admin?: AdminConfig;
  adminAuth?: PublicAdminAuthConfig;
  hasStorage?: boolean;
  configDiagnostics?: ConfigDiagnostic[];
  ai?: SerializedSchemaAIConfig;
  trash?: {
    enabled?: boolean;
    retentionDays?: number | null;
    allowPermanentDelete?: boolean;
  };
  adminHealth?: {
    emailConfigured?: boolean;
    secureAuthSecretConfigured?: boolean;
    authCollectionConfigured?: boolean;
    uploadCollectionConfigured?: boolean;
    trashPurgeOverdue?: boolean;
  };
}
OptionDescription
blocks (optional)
collections (required)
globals (required)
admin (optional)
adminAuth (optional)
hasStorage (optional)
configDiagnostics (optional)
ai (optional)
trash (optional)
adminHealth (optional)

SchemaShape

Exported interface from @dyrected/sdk.

export interface SchemaShape {
  collections: Record<string, object>;
  globals: Record<string, object>;
}
OptionDescription
collections (required)
globals (required)

SerializedCollectionConfig

Exported interface from @dyrected/sdk.

export interface SerializedCollectionConfig {
  slug: string;
  labels?: { singular?: string; plural?: string };
  shared?: boolean;
  siteId?: string;
  ai?: unknown;
  access?: {
    read?: boolean | string;
    create?: boolean | string;
    update?: boolean | string;
    delete?: boolean | string;
  };
  fields: SerializedField[];
  upload?: boolean;
  auth?: boolean;
  audit?: boolean;
  drafts?: boolean;
  defaultView?: string;
  views?: unknown[];
  admin?: Record<string, unknown>;
  detail?: unknown;
  workflow?: unknown;
}
OptionDescription
slug (required)
labels (optional)
shared (optional)
siteId (optional)
ai (optional)
access (optional)
fields (required)
upload (optional)
auth (optional)
audit (optional)
drafts (optional)
defaultView (optional)
views (optional)
admin (optional)
detail (optional)
workflow (optional)

SerializedField

Exported interface from @dyrected/sdk.

export interface SerializedField {
  name: string;
  type: string;
  label?: string;
  required?: boolean;
  unique?: boolean;
  min?: number;
  max?: number;
  step?: number;
  minLength?: number;
  maxLength?: number;
  pattern?: string;
  allowedTypes?: string[];
  maxSize?: number;
  virtual?: boolean;
  promoted?: boolean;
  ai?: {
    exclude?: boolean;
    redact?: boolean | "mask";
    allowRaw?: boolean;
  };
  defaultValue?: unknown;
  options?: unknown;
  relationTo?: string;
  hasMany?: boolean;
  fields?: SerializedField[];
  blocks?: unknown[];
  blockReferences?: string[];
  collection?: string;
  on?: string;
  limit?: number;
  admin?: Record<string, unknown>;
  access?: {
    read?: boolean | string;
    create?: boolean | string;
    update?: boolean | string;
  };
}
OptionDescription
name (required)
type (required)
label (optional)
required (optional)
unique (optional)
min (optional)
max (optional)
step (optional)
minLength (optional)
maxLength (optional)
pattern (optional)
allowedTypes (optional)
maxSize (optional)
virtual (optional)
promoted (optional)
ai (optional)
defaultValue (optional)
options (optional)
relationTo (optional)
hasMany (optional)
fields (optional)
blocks (optional)
blockReferences (optional)
collection (optional)
on (optional)
limit (optional)
admin (optional)
access (optional)

SerializedGlobalConfig

Exported interface from @dyrected/sdk.

export interface SerializedGlobalConfig {
  slug: string;
  label?: string;
  shared?: boolean;
  siteId?: string;
  access?: {
    read?: boolean | string;
    update?: boolean | string;
  };
  fields: SerializedField[];
  admin?: Record<string, unknown>;
  detail?: unknown;
}
OptionDescription
slug (required)
label (optional)
shared (optional)
siteId (optional)
access (optional)
fields (required)
admin (optional)
detail (optional)

SerializedSchemaAIConfig

Exported interface from @dyrected/sdk.

export interface SerializedSchemaAIConfig {
  enabled: boolean;
  provider?: string;
  model?: string;
}
OptionDescription
enabled (required)
provider (optional)
model (optional)

TokenVerificationResult

Exported interface from @dyrected/sdk.

export interface TokenVerificationResult {
  valid: boolean;
  email?: string;
  collection?: string;
  code?: string;
  message?: string;
}
OptionDescription
valid (required)
email (optional)
collection (optional)
code (optional)
message (optional)

TransitionOptions

Options accepted by client.transition().

export interface TransitionOptions {
  /**
   * The revision number currently shown to the user. When provided, the server
   * rejects the transition if the document has changed since it was loaded,
   * preventing lost-update races.
   */
  expectedRevision?: number;
  /** Required for transitions that have `requireComment: true` (e.g. `reject`). */
  comment?: string;
  /**
   * Extra data passed to the transition's server-side `onTransition` handler,
   * for example an amount the handler needs to act on.
   */
  input?: Record<string, unknown>;
}
OptionDescription
expectedRevision (optional)The revision number currently shown to the user. When provided, the server rejects the transition if the document has changed since it was loaded, preventing lost-update races.
comment (optional)Required for transitions that have `requireComment: true` (e.g. `reject`).
input (optional)Extra data passed to the transition's server-side `onTransition` handler, for example an amount the handler needs to act on.

TrashClient

Exported type from @dyrected/sdk.

export type TrashClient = ((collectionSlug?: string) => TrashOperations) & TrashOperations;

TrashEmptyOptions

Exported interface from @dyrected/sdk.

export interface TrashEmptyOptions {
  confirm?: string;
}
OptionDescription
confirm (optional)

TrashEntry

A single trash entry representing a soft-deleted document snapshot.

export interface TrashEntry {
  id: string;
  collection: string;
  docId: string;
  deletedAt: number;
  purgeAt: number | null;
  deletedBy?: string;
  title?: string;
  snapshot: Record<string, unknown>;
  createdAt?: string;
  updatedAt?: string;
}
OptionDescription
id (required)
collection (required)
docId (required)
deletedAt (required)
purgeAt (required)
deletedBy (optional)
title (optional)
snapshot (required)
createdAt (optional)
updatedAt (optional)

TrashKeepOptions

Exported interface from @dyrected/sdk.

export interface TrashKeepOptions {
  purgeAt?: Date | string | number | null;
}
OptionDescription
purgeAt (optional)

TrashListArgs

Exported interface from @dyrected/sdk.

export interface TrashListArgs {
  page?: number;
  limit?: number;
  search?: string;
  [key: string]: unknown;
}
OptionDescription
page (optional)
limit (optional)
search (optional)

TrashOperations

Exported interface from @dyrected/sdk.

export interface TrashOperations {
  list: (args?: TrashListArgs) => Promise<PaginatedResult<TrashEntry>>;
  get: (trashId: string) => Promise<TrashEntry>;
  restore: (trashId: string, options?: TrashRestoreOptions) => Promise<UnknownRecord>;
  restoreMany: (trashIds: string[]) => Promise<{ restored: string[]; failed: unknown[]; count: number }>;
  keep: (trashId: string, options?: TrashKeepOptions | boolean) => Promise<{ message: string; purgeAt: number | null }>;
  purge: (trashId: string) => Promise<{ message: string }>;
  empty: (options?: TrashEmptyOptions | string) => Promise<{ message: string; count: number }>;
}
OptionDescription
list (optional)
get (required)
restore (optional)
restoreMany (required)
keep (optional)
purge (required)
empty (optional)

TrashRestoreOptions

Exported interface from @dyrected/sdk.

export interface TrashRestoreOptions {
  overrides?: Record<string, unknown>;
}
OptionDescription
overrides (optional)

UploadOptions

Options for file uploads. When onProgress is provided and the runtime supports XMLHttpRequest (browsers), the upload reports real byte-level progress. In other environments (SSR, custom fetch) the callback is ignored and the standard fetch path is used.

export interface UploadOptions {
  /** Called with an integer 0–100 as the file bytes are sent. */
  onProgress?: (percent: number) => void;
  /** Abort the in-flight upload. */
  signal?: AbortSignal;
}
OptionDescription
onProgress (optional)Called with an integer 0–100 as the file bytes are sent.
signal (optional)Abort the in-flight upload.

WorkflowDocument

Shape of a document returned from a workflow-enabled collection.

export interface WorkflowDocument {
  id: string;
  _workflow: WorkflowMetadata;
  [key: string]: unknown;
}
OptionDescription
id (required)
_workflow (required)

WorkflowHistoryEntry

A single workflow history entry returned by client.workflowHistory().

export interface WorkflowHistoryEntry {
  id: string;
  collection: string;
  documentId: string;
  transition: string;
  from: string;
  to: string;
  revision: number;
  comment: string | null;
  actorId: string | null;
  createdAt: string;
}
OptionDescription
id (required)
collection (required)
documentId (required)
transition (required)
from (required)
to (required)
revision (required)
comment (required)
actorId (required)
createdAt (required)

On this page

Dyrected| Cloud

Get your backend ready in minutes

Use a managed database, storage, APIs, and admin dashboard without setting up the infrastructure yourself.

Set Up My Backend