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

# Configuration

> Configure the SpendOwl SDK

## Basic Configuration

Configure SpendOwl once during app launch with your API key:

<Tabs>
  <Tab title="SwiftUI">
    ```swift theme={null}
    import SwiftUI
    import SpendOwl

    @main
    struct MyApp: App {
        init() {
            SpendOwl.configure(apiKey: "spendowl_live_xxx")
        }

        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    ```
  </Tab>

  <Tab title="UIKit">
    ```swift theme={null}
    import UIKit
    import SpendOwl

    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
        func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
        ) -> Bool {
            SpendOwl.configure(apiKey: "spendowl_live_xxx")
            return true
        }
    }
    ```
  </Tab>
</Tabs>

<Warning>
  Call `configure()` only once. Subsequent calls are ignored.
</Warning>

## What Happens on Configure

When you call `configure()`, SpendOwl automatically:

1. **Fetches attribution** — Gets the Apple Search Ads attribution token and sends it to SpendOwl servers
2. **Starts purchase tracking** — Observes StoreKit 2 transactions for ROAS calculation
3. **Initializes networking** — Sets up the API client with retry logic

<Note>
  Both attribution and purchase tracking are required for accurate ROAS calculation.
</Note>

## Advanced Configuration

For more control, use `SpendOwlConfiguration`:

```swift theme={null}
let config = SpendOwlConfiguration(
    apiKey: "spendowl_live_xxx",
    timeoutInterval: 30,  // seconds
    maxRetries: 5
)
SpendOwl.configure(config)
```

### Configuration Options

<ParamField path="apiKey" type="String" required>
  Your SpendOwl API key from the [dashboard](https://spendowl.io/dashboard).
</ParamField>

<ParamField path="baseURL" type="URL" default="https://spendowl.io/api">
  The API base URL. Only change this for testing or if instructed by SpendOwl support.
</ParamField>

<ParamField path="timeoutInterval" type="TimeInterval" default="10">
  Network request timeout in seconds. Increase for slow networks.
</ParamField>

<ParamField path="maxRetries" type="Int" default="3">
  Maximum retry attempts for failed requests. Client errors (4xx) are not retried.
</ParamField>

## Check Configuration Status

Verify the SDK is configured before using other methods:

```swift theme={null}
if SpendOwl.isConfigured {
    // SDK is ready
    let attribution = try await SpendOwl.attribution()
}
```

## API Key Best Practices

<AccordionGroup>
  <Accordion title="Use Environment Variables">
    Don't hardcode API keys in source code. Use environment variables or a configuration file:

    ```swift theme={null}
    let apiKey = ProcessInfo.processInfo.environment["SPENDOWL_API_KEY"] ?? ""
    SpendOwl.configure(apiKey: apiKey)
    ```
  </Accordion>

  <Accordion title="Separate Keys for Environments">
    Use different API keys for development and production:

    ```swift theme={null}
    #if DEBUG
    let apiKey = "spendowl_test_xxx"
    #else
    let apiKey = "spendowl_live_xxx"
    #endif

    SpendOwl.configure(apiKey: apiKey)
    ```
  </Accordion>

  <Accordion title="Never Commit Keys">
    Add your config file to `.gitignore` to prevent accidentally committing API keys.
  </Accordion>
</AccordionGroup>

## Thread Safety

SpendOwl is thread-safe. You can call `configure()` from any thread, though calling from the main thread during app launch is recommended.

## Next Steps

<CardGroup cols={2}>
  <Card title="Attribution" icon="bullseye" href="/sdk/attribution">
    Learn how to access attribution data
  </Card>

  <Card title="User Identity" icon="user" href="/sdk/user-identity">
    Link attribution to user accounts
  </Card>
</CardGroup>
