> 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/swift.md).

# Swift

Write and read records from Swift (iOS, macOS) with the Norbix Swift SDK.

The Swift SDK is a Swift package (source and releases: [github.com/norbix-code/sdk-swift](https://github.com/norbix-code/sdk-swift)). It has two libraries: `NorbixApi` (your app's data: records, files, users) and `NorbixHub` (configuration). It needs Swift 5.9 and is built for Apple platforms: iOS 14, macOS 12, tvOS 14, watchOS 7 and visionOS 1 or newer.

This page was run on 2026-10-06 with version **1.8.0** and Swift 6.4 on macOS. All the code below is one file, `Sources/Quickstart/main.swift` of a command-line package: 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 and your project id in `NORBIX_API_KEY` and `NORBIX_PROJECT_ID` — see [Install a Norbix SDK](/codemash/sdks/install.md). The key needs a role that may write records, for example **Data Editor**.

## Install

In Xcode: **File → Add Package Dependencies…**, enter `https://github.com/norbix-code/sdk-swift`, pick **Up to Next Major** from 1.8.0 and add the **NorbixApi** library to your target.

In a `Package.swift`:

```swift
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "Quickstart",
    platforms: [.macOS(.v12)],
    dependencies: [
        .package(url: "https://github.com/norbix-code/sdk-swift.git", exact: "1.8.0"),
    ],
    targets: [
        .executableTarget(
            name: "Quickstart",
            dependencies: [.product(name: "NorbixApi", package: "sdk-swift")]
        ),
    ]
)
```

## Create the client

```swift
import Foundation
import NorbixApi
import NorbixCore // NorbixError lives here

// Reads NORBIX_API_KEY and NORBIX_PROJECT_ID from the environment.
let client = try NorbixApiClient()
```

`import NorbixCore` is needed for `NorbixError` in 1.8.0. To pass the values in code instead: `try NorbixApiClient(projectId: "pr_…", 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 (`client.login(...)`) and call Norbix with the user's token instead.
{% endhint %}

## Write a record

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

```swift
// Write: add one book to the `books` collection.
let book = try JSONSerialization.data(withJSONObject: ["title": "Dune", "pages": 412, "genre": "fiction"])
let created = try await client.database.insertOne([
    "collectionName": "books",
    "document": String(decoding: book, as: UTF8.self),
]) as? [String: Any]
print("Inserted", created?["id"] ?? "")
```

## Read records

`find` returns one page of records in `list.items`. Add `filter`, `sort` or `projection` to the request as in [Search parameters](/codemash/cloud/concepts/search-parameters.md).

```swift
// Read: find the books.
let found = try await client.database.find(["collectionName": "books", "pageSize": 10]) as? [String: Any]
let items = (found?["list"] as? [String: Any])?["items"] as? [[String: Any]] ?? []
for item in items {
    print("\(item["title"] ?? "") — \(item["pages"] ?? "") pages")
}
```

## Handle errors

A failed call throws a `NorbixError` with the gateway's `code` and `message`. Here the schema says `pages` is required:

```swift
// Error handling: the schema requires `pages`, so this insert fails.
do {
    let draft = try JSONSerialization.data(withJSONObject: ["title": "Untitled draft"])
    _ = try await client.database.insertOne([
        "collectionName": "books",
        "document": String(decoding: draft, as: UTF8.self),
    ])
} catch let error as NorbixError {
    print("Failed: \(error.code) — \(error.message)")
}
```

## Run it

```sh
swift run Quickstart
```

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

```
Inserted 6ac54b89212c29912eaddd8b
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).
