> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/sdks/flutter.md).

# Flutter / Dart

Write and read records from Dart and Flutter with the Norbix Dart SDK.

The Dart SDK is [`norbix`](https://pub.dev/packages/norbix) on pub.dev (source: [github.com/norbix-code/sdk-dart](https://github.com/norbix-code/sdk-dart)). It is plain Dart, so it works in Dart programs and in Flutter apps. It has two libraries: `package:norbix/norbix_api.dart` (your app's data) and `package:norbix/norbix_hub.dart` (configuration).

This page was run on 2026-10-06 with `norbix` **2.10.0** — with Dart 3.13 and inside a Flutter 3.44 project. All the code below is one file, `bin/quickstart.dart`: put the blocks one after the other.

## Before you start

* A project with a `books` collection — `title` (text, required), `pages` (number, required), `in_stock` (yes / no), `genre`. Create it in Cloud as in step 3 of the [Quickstart](/codemash/get-started/managed-service/quickstart.md).
* A key whose roles reach **this one project** (for example a service user with the project role **Data Editor**), in `NORBIX_API_KEY` — see [Install a Norbix SDK](/codemash/sdks/install.md).

{% hint style="warning" %}
**The Dart SDK has no project id setting** (2.10.0): it sends no project header, so Norbix takes the project from the key. That works for a key whose roles reach one project, as above. A key or token that reaches several projects cannot pick one from Dart today.
{% endhint %}

## Install

{% tabs %}
{% tab title="Dart" %}

```sh
dart pub add norbix
```

{% endtab %}

{% tab title="Flutter" %}

```sh
flutter pub add norbix
```

{% endtab %}
{% endtabs %}

## Create the client

```dart
import 'dart:convert';

import 'package:norbix/norbix_api.dart';

Future<void> main() async {
  // Reads NORBIX_API_KEY (and NORBIX_API_BASE_URL, NORBIX_API_VERSION) from the environment.
  final api = NorbixApi.fromEnv();
```

`fromEnv` reads Dart's own names: `NORBIX_API_KEY`, `NORBIX_API_BASE_URL` (your own Api address, when you run Norbix yourself) and `NORBIX_API_VERSION`. A Flutter app on a phone has no environment variables — there, pass the values in code:

```dart
final api = NorbixApi(
  config: NorbixConfig(baseUrl: 'https://api.norbix.ai', apiKey: 'nbsu_…'),
);
```

{% hint style="danger" %}
An app that you hand out to people must not contain a service user key — anyone can read it from the app. Sign the user in instead, and call Norbix with the user's token.
{% endhint %}

## Write a record

A record goes in as a JSON string in `document`. The answer is a `Map` with the new record's `id`.

```dart
  // Write: add one book to the `books` collection.
  final created = await api.database.insertOne(
    collectionName: 'books',
    body: {'document': jsonEncode({'title': 'Dune', 'pages': 412, 'genre': 'fiction'})},
  ) as Map<String, dynamic>;
  print('Inserted ${created['id']}');
```

## Read records

`find` returns one page of records in `['list']['items']`. Other request fields (`filter`, `sort`, `projection`, `pageSize`, …) go into `query` — see [Search parameters](/codemash/cloud/concepts/search-parameters.md).

```dart
  // Read: find the books.
  final found = await api.database.find(
    collectionName: 'books',
    query: {'pageSize': 10},
  ) as Map<String, dynamic>;
  for (final book in found['list']['items'] as List) {
    print('${book['title']} — ${book['pages']} pages');
  }
```

## Handle errors

A failed call throws a `NorbixError` with the gateway's `code` and `message`. Subclasses tell the common cases apart (`NorbixAuthError`, `NorbixNotFoundError`, `NorbixRateLimitError`, …). Here the schema says `pages` is required:

```dart
  // Error handling: the schema requires `pages`, so this insert fails.
  try {
    await api.database.insertOne(
      collectionName: 'books',
      body: {'document': jsonEncode({'title': 'Untitled draft'})},
    );
  } on NorbixError catch (err) {
    print('Failed: ${err.code} — ${err.message}');
  }
}
```

## Run it

```sh
dart run bin/quickstart.dart
```

The output (the collection already had *The Hobbit*):

```
Inserted 6ac54bc5212c29912eaddd9a
Dune — 412 pages
The Hobbit — 310 pages
Failed: CM-ERRORS-DATABASE-030 — Field 'pages' is invalid: a value is required
```

## Next steps

* Every operation, with a tab per language: [SDK reference](/codemash/sdks/database.md).
* The same calls from the terminal: [CLI](/codemash/cli/cli.md).
