Guides

SDK Quickstart

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

Install the SDK

Add the Monospace SDK to your project.

npm install @monospace/sdk

This installs the SDK client, CLI, and type generator.

Examples use TypeScript. Enable strict mode so nullable fields keep their | null annotations:

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

In a JavaScript project, skip configuration and generation. Import createClient from @monospace/sdk and go straight to Read Your Data — every query below runs unchanged. See Use the SDK from JavaScript.


Initialize Configuration

Run the interactive setup wizard to create a config file.

npx @monospace/sdk init

The wizard prompts for your instance URL and workspace 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',
  workspace: '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.

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 authenticate via the OS keychain with the login command.

Create the Client

Once types are generated, import createClient from the generated output rather than from @monospace/sdk — the generated factory already knows your schema.

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

const client = createClient({
  url: 'https://example.monospace.io',
  workspace: '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