# Swift and iOS with the CurrencyCore SDK

> Use the official Swift SDK with async/await, configure the key from xcconfig or a backend, decode typed models, and handle ErrorResponse.

Canonical: https://currency-core.com/docs/guides/swift-ios/
Updated: 2026-11-11
Published: 2026-11-11

---
The official `CurrencyCoreSDK` package provides typed `async` methods generated from the OpenAPI contract. Configure it once at startup, then call `CurrencyCoreAPI.convert` or `ratesByBase`. There is no hand-written JSON layer to maintain.

The example targets iOS 16 or later and Swift Package Manager. Free includes 1,000 requests per month at 60 per minute. Test keys use the same reference data and quota, capped at 60 per minute; live keys require a paid plan.

```swift
// Package.swift dependency
.package(url: "https://github.com/CurrencyCore/currencycore-swift.git", from: "0.1.2")
```

```swift

struct Conversion {
    let from: String
    let date: String
    let to: String
    let result: Double
    let rate: Double
}

enum CurrencyCoreService {
    static func configure(apiKey: String) {
        CurrencyCore.configure(apiKey: apiKey)
    }

    static func convert(
        from: String,
        to: String,
        amount: Double
    ) async throws -> Conversion {
        do {
            let response = try await CurrencyCoreAPI.convert(
                from: from,
                to: to,
                amount: amount
            )
            let row = response.results.first!
            return Conversion(
                from: response.from,
                date: response.date,
                to: row.to,
                result: row.result,
                rate: row.rate
            )
        } catch ErrorResponse.error(let status, let data, _, let underlying) {
            throw CurrencyCoreError(
                status: status,
                body: data,
                underlying: underlying
            )
        }
    }
}

struct CurrencyCoreError: Error {
    let status: Int
    let body: Data?
    let underlying: Error
}
```

The decoded response carries the rate date, not a request timestamp:

```json
{
  "from": "USD",
  "amount": 100,
  "date": "2026-11-10",
  "results": [{ "to": "EUR", "result": 92.1, "rate": 0.921 }]
}
```

`CurrencyCore.configure` writes the key and base path to the SDK's shared configuration, so treat it as process-wide setup. If one process needs several keys, use the generated `CurrencyCoreAPI` with an explicit request builder or run each tenant in its own process.

For local builds, put the key in an untracked `.xcconfig` file and read it from `Info.plist`. For a shipping app, assume anything in the bundle is readable and prefer a backend proxy. A value in `Info.plist` is not hidden by code signing.

## Production notes

- App Transport Security blocks cleartext HTTP by default. Keep ATS on and use HTTPS.
- A client-side key can be extracted from an IPA. Treat it as public and proxy when it must remain secret.
- Free history is the last 30 days; older dates return `403`.
- Cache completed dates by date and base. There is no `ETag`, `Last-Modified`, request ID, or quota header, so define your own freshness policy.

## Next steps

- [Official SDKs](/docs/sdks/) for TypeScript, Python, Dart and Kotlin
- [API reference](/docs/api/) and [error codes](/docs/errors/)
- [API key security](/docs/guides/security/) for proxying and rotation
- [All developer guides](/docs/guides/)
