Store your OpenAI API key in Xcode using environment variables or a configuration file
To use OpenAI's API in an Xcode project, you need to store your API key somewhere your app can read it without hardcoding it into your source code. The safest approach is to keep the key in a configuration file or pass it through environment variables, so you never commit it to version control. Xcode provides built-in tools to manage these values during development and testing.
This guide covers the most common methods: storing keys in a local configuration file, using Xcode's scheme environment variables, and managing secrets for different build targets. Each method has trade-offs between security, ease of use, and how you plan to deploy your app later.
Key Takeaways
- Never paste your API key directly into your code — store it in a separate file or environment variable that you exclude from version control.
- Create a Config.plist or JSON file in your project, read it at runtime, and add that file to your .gitignore so it does not sync to GitHub.
- Xcode's scheme editor lets you set environment variables that your app reads during testing without storing them in a file.
- For production apps, use a secure backend service or Apple's Keychain to store the key instead of bundling it with your app.
- Test that your app can read the key correctly before making API calls, because a missing or malformed key will cause silent failures.
Create a configuration file and read it in your app
The simplest method for development is to create a configuration file in your Xcode project that holds your API key. Create a new file called Config.plist (or config.json if you prefer JSON). In this file, add a key-value pair with your OpenAI API key. For example, in a plist file, you would add a key named OPENAI_API_KEY with the value being your actual key.
After creating the file, add it to your .gitignore so it never gets pushed to GitHub or shared with others. In your project root, open or create a .gitignore file and add the line Config.plist (or whatever you named your config file). Then, in your Swift code, read the file at app launch. Use Bundle.main.path(forResource:ofType:) to locate the file, then parse it with PropertyListSerialization or JSONDecoder depending on your format.
Store the key in a property or singleton so you can access it throughout your app without reading the file repeatedly. For example, create a ConfigManager class that loads the key once and exposes it as a static property. This approach keeps your key out of version control and makes it easy to swap keys between development and testing environments by simply editing the local file.
Use Xcode scheme environment variables for testing
If you want to avoid creating a separate file, you can set environment variables directly in Xcode's scheme editor. Open your project in Xcode, go to Product → Scheme → Edit Scheme. Select the Run action on the left, then click the Arguments tab. Under Environment Variables, click the plus button and add a new variable. Name it something like OPENAI_API_KEY and paste your API key as the value.
In your Swift code, read this variable using ProcessInfo.processInfo.environment["OPENAI_API_KEY"]. This method works well for local testing because the variable is only available when you run the app from Xcode — it will not be present in a built app or when running on a device. The key stays in Xcode's memory and is never written to disk, which is slightly more secure than a config file.
The downside is that this approach only works during development. If you build an archive or run the app on a physical device, the environment variable will not be available. For production, you will need a different strategy, such as fetching the key from a secure backend server or using Apple's Keychain framework.
Make API calls with your stored key
Once you have your key stored and readable, create a function that builds an HTTP request to OpenAI's API endpoint. Set the Authorization header to Bearer [your-api-key], replacing [your-api-key] with the key you loaded from your config file or environment variable. Use URLSession to send the request and handle the response.
For example, to call the Chat Completions endpoint, send a POST request to https://api.openai.com/v1/chat/completions with a JSON body containing your message and model choice. Include the header Content-Type: application/json along with the Authorization header. Parse the JSON response to extract the assistant's reply.
Test this locally by running your app in the Xcode simulator and checking the console for any network errors. If you see an authentication error (status code 401), double-check that your key is being read correctly and that it is not expired or revoked in your OpenAI account dashboard.
Exclude your config file from version control
After creating your Config.plist or config.json file, you must prevent it from being committed to Git. Open your .gitignore file in the project root (create one if it does not exist) and add the filename. If your config file is in a subdirectory, use the path relative to the project root, such as Config/Config.plist.
Verify that Git is ignoring the file by running git status in your terminal — the config file should not appear in the list of untracked files. If it was already committed before you added it to .gitignore, you will need to remove it from Git history using git rm --cached Config.plist and then commit that change. This prevents your API key from being visible in your repository history.
When another developer clones your project, they will need to create their own Config.plist file with their own API key. You can include a template file called Config.plist.example in your repository that shows the structure without the actual key, so new team members know what to create.
Use Keychain for production apps
For apps you plan to release on the App Store or distribute to users, storing the API key in a local file or environment variable is not secure enough. Instead, use Apple's Keychain Services framework to store the key securely on the device. Keychain encrypts the data and protects it with the device's security features.
Alternatively, have your app communicate with a backend server that you control. The app sends a request to your server (without the API key), your server makes the API call to OpenAI using its own key, and your server returns the result to the app. This way, your API key never leaves your server and is never exposed to users or the network.
If you use a backend approach, you can add authentication to your server so only your app can make requests — for example, by issuing a unique token to your app that it includes in each request. This prevents other people from using your API key through your server.
Troubleshoot common key-reading errors
If your app cannot read the API key, check these common issues. First, verify that the config file exists in your Xcode project and is included in your app's target. Select the file in Xcode, open the File Inspector on the right, and confirm that your app target is checked under Target Membership. If it is not checked, the file will not be bundled with your app.
Second, confirm that you are using the correct filename and path when reading the file. If you named it Config.plist but your code looks for config.plist (lowercase), it will fail on a real device because iOS is case-sensitive. Test on a physical device or simulator to catch this early.
Third, print the key to the console during development to verify it is being read correctly. Add a line like print("API Key: \(apiKey ?? "NOT FOUND")") right after you load it. If it prints "NOT FOUND", the file is not being read. If it prints a partial key or garbage characters, the file format or parsing logic is wrong.
Frequently Asked Questions
Can I commit my API key to GitHub if my repository is private?
No. Even private repositories can be compromised, and GitHub scans for exposed API keys. If you accidentally commit a key, GitHub will notify you and you should revoke it immediately in your OpenAI account. Always use .gitignore to prevent keys from being committed, regardless of repository visibility.
What happens if someone gets my API key?
They can make API calls on your behalf and you will be charged for them. Revoke the key immediately in your OpenAI account dashboard under API keys, then generate a new one. If you suspect unauthorized use, check your usage dashboard to see what calls were made and when.
Do I need a different key for development and production?
You can use the same key, but it is safer to create separate keys in your OpenAI account — one for development and one for production. This way, if your development key is exposed, your production key remains secure. You can also set usage limits on each key to catch unexpected behavior.
How do I test my app without using my real API key?
Use a mock API key during testing and replace it with your real key before release. Alternatively, mock the URLSession response in your unit tests so your code never actually calls OpenAI's servers. This lets you test your app's logic without spending API credits.
Should I store the API key in UserDefaults?
No. UserDefaults is not encrypted and can be read by other apps or tools. Use a config file that you exclude from version control, environment variables in Xcode, or Keychain for production. UserDefaults is fine for non-sensitive data like user preferences.