How to Allowlist GPT-6 Models for Each OpenAI Project
Nobody decides to burn money on the priciest model. It just happens to be in the dropdown. This guide sets up an OpenAI project allowlist with the Admin API, so each project can call only the GPT-6 models you approved, and adds a spend alert per project. At the end, Sol and Luna are the default and Astra is an exception someone had to ask for.
Why GPT-6 Astra needs a gate
The OpenAI pricing page lists standard short-context rates per 1M tokens: Astra is $10 input and $50 output, Sol is $2 and $10, Luna is $0.10 and $0.50. Astra costs 5x Sol and 100x Luna.
Take a workload of 10M input and 2M output tokens a month. That is $200 on Astra, $40 on Sol and $2 on Luna. Long-context requests (over 272K input tokens) cost more on every model, so the gap only widens.
An allowlist moves the choice from "whoever wrote the code" to "a conversation with the person who owns the budget."
Step 1: Create an admin key
Create an Admin API key on the admin keys page. Per the Admin APIs guide, admin keys can't call non-administration endpoints, so this key can change policy but can't run a completion. Store it in a secret manager, not in code.
export OPENAI_ADMIN_KEY="<your-admin-key>"
The examples below read the key from OPENAI_ADMIN_KEY.
Step 2: Find your project IDs
curl https://api.openai.com/v1/organization/projects \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY"
Each project comes back with an id, a name and a status. Archived projects are left out unless you ask for them. Copy the IDs (they start with proj_) for the projects you want to restrict.
Step 3: Set the OpenAI project allowlist to Sol and Luna
curl -X POST https://api.openai.com/v1/organization/projects/<project-id>/model_permissions \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "allow_list",
"model_ids": ["gpt-6-sol", "gpt-6-luna"]
}'
In allow_list mode only the listed models work. deny_list blocks the listed ones and allows everything else, so it also allows whatever you forgot to name. Use allow_list.
Model IDs must be visible to your organization. Send the complete list on every update and treat each call as writing the whole policy.
Step 4: Grant Astra by exception
Give Astra to a separate project, named for the team and the reason, so your exception list is a project list instead of a spreadsheet.
curl -X POST https://api.openai.com/v1/organization/projects/<exception-project-id>/model_permissions \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "allow_list",
"model_ids": ["gpt-6-astra", "gpt-6-sol", "gpt-6-luna"]
}'
Read the policy back to confirm it. The response has mode, model_ids and an object of project.model_permissions.
curl https://api.openai.com/v1/organization/projects/<exception-project-id>/model_permissions \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY"
To end an exception, post the Sol and Luna list again.
Step 5: Add OpenAI project spend alerts
curl -X POST https://api.openai.com/v1/organization/projects/<project-id>/spend_alerts \
-H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"threshold_amount": 5000,
"currency": "USD",
"interval": "month",
"notification_channel": {
"type": "email",
"recipients": ["<budget-owner>@example.com"],
"subject_prefix": "[OpenAI spend]"
}
}'
threshold_amount is in cents, so 5000 is $50. Only USD, month and the email channel are supported. Set a low threshold on default projects and a deliberate one on the Astra project, for example 20000 ($200), so drift shows up as an email instead of an invoice line.
If you manage this as code, the Terraform guide documents an openai_project_spend_alert resource with the same fields.
Step 6: Lock down who can create keys
An allowlist is only as good as the keys behind it. In the API Key Governance section of Platform settings, admins can allow only service-account keys, allow only user-owned project keys, or disable new key creation. The production best practices add that organization restrictions win over project settings, which can only tighten them. Admins can also enforce a maximum key lifetime.
Gotchas
- Exact IDs only.
gpt-6.1-solis a separate model ID fromgpt-6-sol. Allowing one does not allow the other, so expect a request when a team moves to a newer model. - Alerts don't block. Spend alerts are notifications. An organization hard limit (
POST /v1/organization/spend_limit) exists, but when it is reached affected API requests get a 429, so read the spend limits docs before using it in production. - Governance is forward-looking. The key creation setting applies to new keys only. Review the existing ones.
- Guard the admin key. It can rewrite your policy, so give it to as few people as possible.
- Test the wall. Call a blocked model with a key from that project and confirm it is refused.
- SDKs work too. They take
admin_api_key(Python 2.34.0 or later) oradminAPIKey(Node 6.36.0 or later) if you prefer them to curl.
A per-project allowlist plus a spend alert turns "which model are we on?" from a surprise on the invoice into a decision someone made on purpose.