# Authentication All requests to the Ionworks API require an API key. This page covers how to obtain a key and configure the client. ## Obtaining an API key You can generate an API key from the [Ionworks account settings](https://app.ionworks.com/account) page. Keep the key safe — it will only be shown once. ## Configuration The client reads credentials from environment variables by default. The repository includes a `.env.example` file you can copy as a starting point: ```bash cp .env.example .env ``` Then fill in your values: ```{eval-rst} .. literalinclude:: /../../.env.example :language: bash :caption: .env.example ``` Set the required `IONWORKS_API_KEY` variable, and uncomment any optional variables you need. If you work with pipelines or any other project-scoped resource, set `IONWORKS_PROJECT_ID` — you can copy it from the project settings page at `https://app.ionworks.com/projects//settings`. (`PROJECT_ID` is still accepted for backwards compatibility but is deprecated and will be removed in a future release.) The client reads its configuration from environment variables but does not load `.env` files itself. Load your `.env` explicitly with [python-dotenv](https://pypi.org/project/python-dotenv/) before constructing the client: ```python from dotenv import load_dotenv load_dotenv() import ionworks as iw client = iw.api.Client() ``` Alternatively, export the variables in your shell: ```bash export IONWORKS_API_KEY="your-api-key" ``` ## Initializing the client ```python import ionworks as iw # Reads IONWORKS_API_KEY, IONWORKS_API_URL, and IONWORKS_PROJECT_ID # from the environment. client = iw.api.Client() ``` You can also pass credentials directly — this takes precedence over environment variables: ```python import ionworks as iw client = iw.api.Client( api_key="your-api-key", api_url="https://api.ionworks.com", project_id="your-project-id", ) ``` ### Default project ID When `IONWORKS_PROJECT_ID` is set (or `project_id=` is passed to the client), every sub-client method that takes a `project_id` argument uses that value as the default. You can still pass an explicit `project_id` to override it on a per-call basis: ```python # Uses IONWORKS_PROJECT_ID client.study.create({"name": "Discharge study"}) # Override for a single call client.study.create({"name": "Discharge study"}, project_id="other-project") ``` This means scripts no longer need to thread a `project_id` through every call site or stamp it into every payload. ### Request configuration The client supports configuring request timeout and retry behavior: ```python import ionworks as iw # Default: 10 second timeout, 5 retries client = iw.api.Client() # Custom timeout (in seconds) client = iw.api.Client(timeout=30) # Custom maximum retries client = iw.api.Client(max_retries=3) # Both custom client = iw.api.Client(timeout=20, max_retries=10) ``` - **timeout**: Request timeout in seconds. Defaults to 10 seconds. - **max_retries**: Maximum number of retries for failed requests. Defaults to 5. Retries occur automatically on connection errors, timeouts, and 5xx server errors with exponential backoff. ## Verifying connectivity Call `health_check()` to confirm the client can reach the API: ```python health = client.health_check() print(health) ``` ## Troubleshooting | Symptom | Cause | Fix | |---|---|---| | `ValueError` on init | `IONWORKS_API_KEY` is not set and no key was passed | Set the environment variable or pass `api_key=` | | `IonworksError` with status 401 | Invalid or revoked API key (keys do not expire, but regenerating one invalidates the previous key) | Regenerate the key in account settings | | Connection timeout | Network or firewall issue, or default timeout too short | Check that `https://api.ionworks.com` is reachable, or increase timeout: `iw.api.Client(timeout=30)` | | Requests timing out frequently | Default 10s timeout may be too short for slow operations | Increase timeout: `iw.api.Client(timeout=60)` | ## Next steps With the client authenticated you can start managing cells — see {doc}`cell_specifications`.