Guides

SDK Quickstart

Install the Monospace SDK, generate types from your schema, and query your data with full TypeScript autocomplete.

Install the SDK

Add the Monospace SDK to your project.

terminal
npm install @monospace/sdk

This installs the SDK client, CLI, and type generator. You also need TypeScript with strict mode enabled:

tsconfig.json
{
  "compilerOptions": {
    "strict": true
  }
}

Initialize Configuration

Run the interactive setup wizard to create a config file.

terminal
npx @monospace/sdk init

The wizard prompts for your instance URL and project identifier, then writes a monospace.config.ts file:

monospace.config.ts
import { defineConfig } from '@monospace/sdk/config'

export default defineConfig({
  url: 'https://example.monospace.io',
  project: 'blog',
  output: './src/generated/monospace',
})

output is where the generated typed client will live. The default is ./src/generated/monospace.


Generate Types

Run the generator to introspect your Monospace instance and produce a typed client.

terminal
npx @monospace/sdk generate

The generator connects to your instance, reads the schema via the OpenAPI endpoint, and writes a single index.ts file:

your-project/
├── src/
│   └── generated/
│       └── monospace/
│           └── index.ts      ← generated typed client
├── monospace.config.ts
├── package.json
└── tsconfig.json

The generated file contains:

  • TypeScript types for every collection, including field types, filter inputs, and relation shapes
  • A pre-typed createClient factory with your Schema baked in — no manual generic parameters needed
  • Per-collection type aliases like ArticleKey, ArticleCreateOneInput, ArticleReadManyResult, and more
The generator needs schema access. Set MONOSPACE_API_KEY in a .env file, or run npx @monospace/sdk login to authenticate via the OS keychain.

Create the Client

Import createClient from the generated output — not from @monospace/sdk directly. The generated factory already knows your schema.

src/client.ts
import { createClient } from './generated/monospace';

const client = createClient({
  url: 'https://example.monospace.io',
  project: 'blog',
  apiKey: process.env.MONOSPACE_API_KEY,
});

That's it. client is now a fully typed Monospace client. Every collection in your schema is available as a property — client.Articles, client.Authors, client.Tags — with autocomplete for every CRUD method and field name.

This is the payoff of the codegen step. Type client. in your editor and you should see every collection listed. Select one, type .readMany({ fields: [ and your field names appear as autocomplete suggestions. No manual type definitions, no runtime validation — the types come directly from your schema.


Read Your Data

Fetch articles with typed field selection.

src/index.ts
const articles = await client.Articles.readMany({
  fields: ['id', 'title', 'status'],
});

// TypeScript knows the exact shape:
// {
//   id: string | null;
//   title: string | null;
//   status: string | null;
// }[]

for (const article of articles) {
  console.log(article.title);
}

The return type narrows to match your fields array. Request three fields, get three fields in the type. Add a field, the type updates. Remove one, TypeScript flags any code that references it.

readMany returns up to 100 items by default. Use limit and offset for pagination:

const page = await client.Articles.readMany({
  fields: ['id', 'title'],
  limit: 20,
  offset: 40,
});

Fetch a single item by key:

const article = await client.Articles.readOne({
  key: 1,
  fields: ['id', 'title', 'status'],
});

// TypeScript infers a single object (not an array):
// {
//   id: string | null;
//   title: string | null;
//   status: string | null;
// }

Create and Update Items

Create an article with typed input validation.

const created = await client.Articles.createOne({
  data: {
    title: 'Getting Started with Monospace',
    status: 'draft',
  },
  fields: ['id', 'title', 'status'],
});

console.log(created.id); // typed as string | null

The data object is typed against your schema — TypeScript enforces required fields and rejects unknown properties.

Update an existing article by key:

const updated = await client.Articles.updateOne({
  key: created.id,
  data: {
    status: 'published',
  },
  fields: ['id', 'status'],
});

console.log(updated.status); // typed as string | null

Update inputs make every field optional — include only the fields you want to change.


Next Steps

  • Filtering — narrow results with typed filter operators like _eq, _contains, and _in
  • Field Selection — control which fields are returned, including nested relations
  • Relational Data — fetch and write nested relations in a single request
  • Type System — extract result types for component props, reusable queries with satisfies, and more
Copyright © 2026