> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corsair.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift

> Call your hosted Corsair Cloud project from Swift, with async/await and typed decoding.

`CorsairCloud` is a small Swift client for a hosted [Corsair Cloud](/cloud/overview)
project. It uses `URLSession` and `async`/`await`. Give it your API key, and
every plugin your runtime has is callable over HTTP.

## 1. Install

Add it to your `Package.swift`. The package lives under `clients/swift` in the
`corsair` monorepo. Until a root-level Swift mirror ships, add it as a local path
dependency from a checkout of `corsair`:

```swift theme={null}
.package(path: "../corsair/clients/swift"),
// then in your target: .product(name: "CorsairCloud", package: "CorsairCloud")
```

## 2. Add your API key

Copy your project's **API key** (`ck_cloud_…`) from the dashboard Overview page.
Keep it on a server; don't ship it inside an app you distribute. The client
derives its own URL from the key:

```swift theme={null}
import CorsairCloud

let corsair = CorsairCloud(apiKey: ProcessInfo.processInfo.environment["CORSAIR_CLOUD_KEY"]!)
```

## 3. Make a call

Pick a user (a "tenant"), then call any operation on any plugin your runtime has:

```swift theme={null}
let result = try await corsair.tenant("acme").call("notion", "pages.searchPage", args: ["query": "roadmap"])
```

`tenant("acme")` runs the call as your user "acme". By default `result` is a
`JSONValue`. To get a typed result, pass your own `Decodable` and Corsair decodes
it for you:

```swift theme={null}
struct Page: Decodable { let id: String }
struct SearchResult: Decodable { let results: [Page] }

let typed = try await corsair.tenant("acme")
    .call("notion", "pages.searchPage", as: SearchResult.self)
```

## 4. Connect a user's account

A tenant can only call Notion after they have connected their Notion account.
Create a connect link and send the user to it:

```swift theme={null}
let link = try await corsair.manage.createConnectLink(plugin: "notion", tenantId: "acme")
// open link.connectUrl
```

After they authorize, check who is connected:

```swift theme={null}
let status = try await corsair.manage.connectionStatus(tenantId: "acme")
// ["notion": "connected"]

try await corsair.manage.disconnect(plugin: "notion", tenantId: "acme")
```

## Handle errors

Any non-2xx response throws `CorsairError`:

```swift theme={null}
do {
    _ = try await corsair.tenant("acme").call("notion", "pages.searchPage", args: [:])
} catch let error as CorsairError {
    if error.code == "not_connected" {
        // send the user through createConnectLink first
    }
}
```

Its fields: `code` (machine reason, branch on this), `status` (HTTP status),
`message`, and the upstream provider's status when the error came from them.
