This service exposes a versioned HTTP adapter over the local Codex app-server. The stable surface for browser-based coding agents is under /api/v1. Search is enabled by default, managed projects resume the latest Codex thread for the same workspace, and approval-aware coding flows remain explicit rather than hidden.
Version: v1.0.48. Customer API authentication accepts a System Token or User API Key. Admin API endpoints remain hidden until an authorized admin signs in on this page.
Exact model ID: power-ai
Power AI is a managed model alias. Send model=power-ai to use the service's configured Power AI destination. The selected provider can change without changing this model ID. Existing account billing and key restrictions apply. This is a service-managed alias, not the official name of a separate foundation model.
https://codexapi.pro as the API host. SDKs that append endpoint names normally need https://codexapi.pro/v1 as their base URL; do not append /v1 twice.Authorization: Bearer YOUR_API_KEY and model: power-ai. A dashboard login session, provider key or reseller-management key is not a substitute for the customer's model API key.Power AI accepts Chat Completions, Responses and Anthropic-style Messages requests. The public model ID stays power-ai even when its managed destination changes. Reasoning behavior follows the current routing policy; specifying this alias does not pin a particular upstream or effort level.
Download customer OpenAPI schema. Import this schema into your API client and choose a Power AI request example. Customer inference and reseller management use separate schemas.
Bash: set API_KEY to a System Token or User API Key from this site's dashboard before running these commands.
curl --fail-with-body https://codexapi.pro/v1/models \
-H "Authorization: Bearer $API_KEY"Read the assistant reply from choices[0].message.content. Inspect tool_calls if the reply asks to use a function.
curl --fail-with-body --max-time 180 https://codexapi.pro/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"power-ai","max_tokens":64,"messages":[{"role":"user","content":"Reply exactly OK."}]}'Read text from output items containing output_text blocks. Response IDs and usage totals vary by request.
curl --fail-with-body --max-time 180 https://codexapi.pro/v1/responses \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"power-ai","input":"Reply exactly OK.","max_output_tokens":64}'Use /v1/messages and include the anthropic-version header. Read text blocks from content. No dashboard model change is needed when the request explicitly names power-ai.
curl --fail-with-body --max-time 180 https://codexapi.pro/v1/messages \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"power-ai","max_tokens":64,"messages":[{"role":"user","content":"Reply exactly OK."}]}'This Responses example keeps the connection open for server-sent events. Handle text deltas, response.completed and error events; HTTP 200 alone does not prove a successful generation. Messages streams use content_block_delta and message_stop instead.
curl --fail-with-body --max-time 180 -N https://codexapi.pro/v1/responses \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"power-ai","input":"Reply exactly OK.","max_output_tokens":64,"stream":true}'Your application must execute get_project_name locally. Return a role=tool message with the matching tool_call_id after the complete assistant tool_calls message, then submit the conversation again. Do not omit a tool result or execute an unapproved function. Tools and images remain subject to the active destination's capabilities.
curl --fail-with-body --max-time 180 https://codexapi.pro/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"power-ai","messages":[{"role":"user","content":"Use get_project_name to read the current project name."}],"tools":[{"type":"function","function":{"name":"get_project_name","description":"Read the name of the current project.","parameters":{"type":"object","properties":{},"additionalProperties":false}}}],"tool_choice":{"type":"function","function":{"name":"get_project_name"}},"max_tokens":256}'Python 3, standard library only. Set API_KEY in your environment. This sends one request and prints the answer and support request ID.
import json
import os
from urllib.request import Request, urlopen
payload = {'model': 'power-ai', 'max_tokens': 64, 'messages': [{'role': 'user', 'content': 'Reply exactly OK.'}]}
request = Request(
"https://codexapi.pro/v1/chat/completions",
data=json.dumps(payload).encode("utf-8"),
headers={"Authorization": "Bearer " + os.environ["API_KEY"],
"Content-Type": "application/json"},
method="POST",
)
with urlopen(request, timeout=180) as response:
result = json.load(response)
print(result["choices"][0]["message"]["content"])
print("Request ID:", response.headers.get("x-request-id", "not supplied"))Run with Node.js 18 or later. Keep the key on your server, never in public browser JavaScript. Set API_KEY before running the script.
async function main() {
if (!process.env.API_KEY) throw new Error("Set API_KEY first");
const response = await fetch("https://codexapi.pro/v1/chat/completions", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"model": "power-ai", "max_tokens": 64, "messages": [{"role": "user", "content": "Reply exactly OK."}]}),
signal: AbortSignal.timeout(180000),
});
const requestId = response.headers.get("x-request-id");
if (!response.ok) throw new Error(`HTTP ${response.status}; request ID ${requestId}`);
const result = await response.json();
console.log(result.choices[0].message.content);
console.log("Request ID:", requestId);
}
main().catch(error => { console.error(error.message); process.exitCode = 1; });Set the API_KEY environment variable to your own key, then paste this into PowerShell. This example does not overwrite any CLI configuration.
$ErrorActionPreference = 'Stop'
if (-not $env:API_KEY) { throw 'Set API_KEY first' }
$body = @{
model = 'power-ai'
max_tokens = 64
messages = @(@{ role = 'user'; content = 'Reply exactly OK.' })
} | ConvertTo-Json -Depth 10
$result = Invoke-RestMethod -Method Post -Uri 'https://codexapi.pro/v1/chat/completions' -TimeoutSec 180 -Headers @{ Authorization = "Bearer $env:API_KEY" } -ContentType 'application/json' -Body $body
$result.choices[0].message.content401: Check that the key belongs to this site and has not been revoked. 402: Check available wallet credit or matching Unlimited coverage. 403: Check key permissions and VIP entitlement if using VIP. 429: Respect Retry-After and avoid overlapping retries. 502/503: The current upstream could not complete the request; save the request ID for support. Do not resend a completed request blindly.
Image input uses OpenAI image_url blocks on Chat Completions and Anthropic image blocks on Messages. Never strip an image to make a request appear successful; verify support through the configured destination. Local file, shell and editor tools run in your client, not automatically on the API server.
Restricted operator access
Sign in with the authorized admin account to add the protected Admin API endpoints to this page. Customer documentation remains public.
Authorization: Bearer g2g-codex-example. The System Token resolves to the user's active wallet key internally, so wallet balance, token usage, Stripe top-ups, and FUP checks stay attached to the correct account.CodexAPI.pro exposes additive compatibility endpoints for coding clients that expect the official OpenAI and Anthropic-style HTTP surfaces. These endpoints use the same wallet, internal rate cards, model-selection policy, and live routing source of truth as the existing CLI endpoints.
POST /v1/responses creates generations for supported GPT models and power-ai, including streaming and function tools where the selected upstream supports them.POST /v1/chat/completions accepts OpenAI Chat Completions payloads and adapts them into the active Responses route, so it works across the currently configured runtime path.POST /v1/completions supports legacy text-completion clients by adapting prompts into the same Responses route.POST /v1/messages and POST /v1/messages/count_tokens provide Anthropic-compatible Claude Code access for Opus 5 with local client tools preserved.GET /v1/models, GET /v1/models/{model}, response lookup, response input item listing, chat-completion listing, chat-completion retrieval, update, and delete endpoints are included for SDK compatibility.These examples automatically use the bearer value in the field above. When a client opens this page from the dashboard, that value is their Codex API username. Replace the prompt text and project names as needed.
Use the customer's Codex API username with the official OpenAI package installed by npm install -g @openai/codex@0.147.0. The API compatibility target is Codex CLI 0.147.0. Do not run codex login for CodexAPI.pro; configure CodexAPI.pro as a custom Responses provider and save the username in ~/.codex/config.toml using the dashboard's one-time setup command.
After the one-time setup has written CodexAPI.pro into the normal Codex config, users can return with codex, codex --search, codex resume --search, or any other normal Codex opening command without repeating API setup.
For non-interactive live-search runs, use codex --search exec .... The current official CLI rejects codex exec --search ....
The dashboard returns a token-specific command after creation; the generic provider shape is:
{
"providerId": "codexapi",
"providerName": "CodexAPI.pro",
"officialCliVersion": "0.147.0",
"officialInstallTag": "0.147.0",
"officialInstallCommand": "npm install -g @openai/codex@0.147.0",
"baseUrl": "https://api-canada.codexapi.pro/v1",
"envKey": "CODEXAPI_CODEX_API_KEY",
"wireApi": "responses",
"model": "gpt-5.6",
"reasoningEffort": "xhigh",
"modelsUrl": "https://api-canada.codexapi.pro/v1/models",
"responsesUrl": "https://api-canada.codexapi.pro/v1/responses",
"codexHome": "$HOME/.codex",
"configArgs": [
"-c 'model_provider=\"codexapi\"'",
"-c 'model_providers.codexapi.name=\"CodexAPI.pro\"'",
"-c 'model_providers.codexapi.base_url=\"https://api-canada.codexapi.pro/v1\"'",
"-c 'model_providers.codexapi.env_key=\"CODEXAPI_CODEX_API_KEY\"'",
"-c 'model_providers.codexapi.wire_api=\"responses\"'",
"-c 'model_providers.codexapi.supports_websockets=false'",
"-c 'model_reasoning_effort=\"xhigh\"'",
"-c 'features.apps=false'",
"-c 'approval_policy=\"never\"'",
"-c 'sandbox_mode=\"danger-full-access\"'"
],
"persistentConfigToml": "model = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\n",
"linuxSetupAndStartCommand": "set -e\nif ! command -v npm >/dev/null 2>&1; then\n if command -v apt-get >/dev/null 2>&1; then\n sudo apt-get update\n sudo apt-get install -y ca-certificates curl gnupg\n curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -\n sudo apt-get install -y nodejs git\n else\n echo \"Install Node.js LTS and npm first, then rerun this block.\" >&2\n exit 1\n fi\nfi\nnpm install -g @openai/codex@0.147.0\nCODEX_HOME_DIR=\"$HOME/.codex\"\nCONFIG_PATH=\"$CODEX_HOME_DIR/config.toml\"\nmkdir -p \"$CODEX_HOME_DIR\" 2>/dev/null || true\nif [ -e \"$CODEX_HOME_DIR\" ] && [ ! -w \"$CODEX_HOME_DIR\" ]; then\n echo \"Fixing ownership of $CODEX_HOME_DIR for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown -R \"$(id -u):$(id -g)\" \"$CODEX_HOME_DIR\"; fi\nfi\nif [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; then\n echo \"Fixing ownership of $CONFIG_PATH for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown \"$(id -u):$(id -g)\" \"$CONFIG_PATH\"; fi\nfi\nmkdir -p \"$CODEX_HOME_DIR\"\nif [ ! -w \"$CODEX_HOME_DIR\" ] || { [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; }; then\n echo \"Cannot write Codex config at $CONFIG_PATH. Run: sudo chown -R \\\"$(id -u):$(id -g)\\\" \\\"$CODEX_HOME_DIR\\\"\" >&2\n exit 1\nfi\nrm -rf \"$CODEX_HOME_DIR/cache/codex_apps_tools\" 2>/dev/null || true\nCODEXAPI_BACKUP_TS=\"$(date +%Y%m%d%H%M%S)\"\nCODEXAPI_CONFIG_SNIPPET=\"$(mktemp)\"\ncat > \"$CODEXAPI_CONFIG_SNIPPET\" <<'TOML'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\nTOML\npython3 - \"$CONFIG_PATH\" \"$CODEXAPI_CONFIG_SNIPPET\" <<'PY'\nimport os, re, shutil, sys\nfrom pathlib import Path\n\npath = Path(sys.argv[1]).expanduser()\nsnippet = Path(sys.argv[2]).read_text()\npath.parent.mkdir(parents=True, exist_ok=True)\nif path.exists():\n shutil.copy2(path, f\"{path}.backup.{os.environ.get('CODEXAPI_BACKUP_TS', 'manual')}\")\noriginal = path.read_text() if path.exists() else \"\"\ntop_keys = {\"model\", \"model_provider\", \"model_reasoning_effort\", \"approval_policy\", \"sandbox_mode\"}\nsection_re = re.compile(r\"^\\s*\\[[^\\]]+\\]\\s*$\")\nkey_re = re.compile(r\"^\\s*([A-Za-z0-9_-]+)\\s*=\")\nstale_mcp_re = re.compile(r\"^\\s*\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])\")\nsnippet_lines = snippet.strip().splitlines()\nfirst_section = next((i for i, line in enumerate(snippet_lines) if section_re.match(line.strip())), len(snippet_lines))\ntop = snippet_lines[:first_section]\nprovider = []\nfeature_apps = 'apps = false'\ni = first_section\nwhile i < len(snippet_lines):\n line = snippet_lines[i]\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", line.strip()):\n provider = snippet_lines[i:]\n break\n i += 1\nclean = []\nskip_codexapi = False\nskip_stale_mcp = False\nin_section = False\nin_features = False\nfeatures_seen = False\nfor line in original.splitlines():\n stripped = line.strip()\n if stale_mcp_re.match(stripped):\n skip_stale_mcp = True\n in_features = False\n continue\n if skip_stale_mcp and section_re.match(stripped):\n skip_stale_mcp = False\n if skip_stale_mcp:\n continue\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", stripped):\n skip_codexapi = True\n in_features = False\n continue\n if skip_codexapi and section_re.match(stripped):\n skip_codexapi = False\n if skip_codexapi:\n continue\n if section_re.match(stripped):\n in_section = True\n in_features = stripped == '[features]'\n features_seen = features_seen or in_features\n if not in_section:\n m = key_re.match(line)\n if m and m.group(1) in top_keys:\n continue\n if in_features:\n m = key_re.match(line)\n if m and m.group(1) == 'apps':\n continue\n clean.append(line)\nparts = []\nparts.extend(top)\nparts.append('')\ninserted_feature = False\nfor line in clean:\n parts.append(line)\n if line.strip() == '[features]':\n parts.append(feature_apps)\n inserted_feature = True\nif not features_seen:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(['[features]', feature_apps])\nif provider:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(provider)\npath.write_text('\\n'.join(line for line in parts if line is not None).rstrip() + '\\n')\nPY\nrm -f \"$CODEXAPI_CONFIG_SNIPPET\"\necho \"CodexAPI.pro is configured. Future sessions can start with codex or codex resume --search.\"\ncodex --search",
"macosSetupAndStartCommand": "set -e\nBREW_BIN=\"$(command -v brew 2>/dev/null || true)\"\nif [ -z \"$BREW_BIN\" ] && [ -x /opt/homebrew/bin/brew ]; then BREW_BIN=\"/opt/homebrew/bin/brew\"; fi\nif [ -z \"$BREW_BIN\" ] && [ -x /usr/local/bin/brew ]; then BREW_BIN=\"/usr/local/bin/brew\"; fi\nif [ -z \"$BREW_BIN\" ]; then\n /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n if [ -x /opt/homebrew/bin/brew ]; then BREW_BIN=\"/opt/homebrew/bin/brew\"; fi\n if [ -z \"$BREW_BIN\" ] && [ -x /usr/local/bin/brew ]; then BREW_BIN=\"/usr/local/bin/brew\"; fi\nfi\nif [ -z \"$BREW_BIN\" ]; then echo \"Homebrew installation finished but brew was not found. Open a new Terminal and rerun this setup.\" >&2; exit 1; fi\neval \"$(\"$BREW_BIN\" shellenv)\"\nbrew list node >/dev/null 2>&1 || brew install node\nbrew list git >/dev/null 2>&1 || brew install git\nhash -r 2>/dev/null || true\nif ! npm install -g @openai/codex@0.147.0; then\n echo \"Global npm install failed. Retrying with a user-owned npm prefix at $HOME/.npm-global.\"\n mkdir -p \"$HOME/.npm-global\"\n npm config set prefix \"$HOME/.npm-global\"\n export PATH=\"$HOME/.npm-global/bin:$PATH\"\n npm install -g @openai/codex@0.147.0\nfi\nexport PATH=\"$(npm config get prefix)/bin:$PATH\"\nhash -r 2>/dev/null || true\nappend_codexapi_path() {\n profile=\"$1\"\n mkdir -p \"$(dirname \"$profile\")\"\n touch \"$profile\"\n if ! grep -q \"# BEGIN CODEXAPI_PRO_NPM_PATH\" \"$profile\" 2>/dev/null; then\n cat >> \"$profile\" <<'ENV'\n# BEGIN CODEXAPI_PRO_NPM_PATH\nexport PATH=\"$HOME/.npm-global/bin:/opt/homebrew/bin:/usr/local/bin:$PATH\"\n# END CODEXAPI_PRO_NPM_PATH\nENV\n fi\n}\nappend_codexapi_path \"$HOME/.zshrc\"\nappend_codexapi_path \"$HOME/.zprofile\"\nappend_codexapi_path \"$HOME/.bashrc\"\nappend_codexapi_path \"$HOME/.profile\"\ncodex --version\nCODEX_HOME_DIR=\"$HOME/.codex\"\nCONFIG_PATH=\"$CODEX_HOME_DIR/config.toml\"\nmkdir -p \"$CODEX_HOME_DIR\" 2>/dev/null || true\nif [ -e \"$CODEX_HOME_DIR\" ] && [ ! -w \"$CODEX_HOME_DIR\" ]; then\n echo \"Fixing ownership of $CODEX_HOME_DIR for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown -R \"$(id -u):$(id -g)\" \"$CODEX_HOME_DIR\"; fi\nfi\nif [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; then\n echo \"Fixing ownership of $CONFIG_PATH for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown \"$(id -u):$(id -g)\" \"$CONFIG_PATH\"; fi\nfi\nmkdir -p \"$CODEX_HOME_DIR\"\nif [ ! -w \"$CODEX_HOME_DIR\" ] || { [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; }; then\n echo \"Cannot write Codex config at $CONFIG_PATH. Run: sudo chown -R \\\"$(id -u):$(id -g)\\\" \\\"$CODEX_HOME_DIR\\\"\" >&2\n exit 1\nfi\nrm -rf \"$CODEX_HOME_DIR/cache/codex_apps_tools\" 2>/dev/null || true\nCODEXAPI_BACKUP_TS=\"$(date +%Y%m%d%H%M%S)\"\nCODEXAPI_CONFIG_SNIPPET=\"$(mktemp)\"\ncat > \"$CODEXAPI_CONFIG_SNIPPET\" <<'TOML'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\nTOML\npython3 - \"$CONFIG_PATH\" \"$CODEXAPI_CONFIG_SNIPPET\" <<'PY'\nimport os, re, shutil, sys\nfrom pathlib import Path\n\npath = Path(sys.argv[1]).expanduser()\nsnippet = Path(sys.argv[2]).read_text()\npath.parent.mkdir(parents=True, exist_ok=True)\nif path.exists():\n shutil.copy2(path, f\"{path}.backup.{os.environ.get('CODEXAPI_BACKUP_TS', 'manual')}\")\noriginal = path.read_text() if path.exists() else \"\"\ntop_keys = {\"model\", \"model_provider\", \"model_reasoning_effort\", \"approval_policy\", \"sandbox_mode\"}\nsection_re = re.compile(r\"^\\s*\\[[^\\]]+\\]\\s*$\")\nkey_re = re.compile(r\"^\\s*([A-Za-z0-9_-]+)\\s*=\")\nstale_mcp_re = re.compile(r\"^\\s*\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])\")\nsnippet_lines = snippet.strip().splitlines()\nfirst_section = next((i for i, line in enumerate(snippet_lines) if section_re.match(line.strip())), len(snippet_lines))\ntop = snippet_lines[:first_section]\nprovider = []\nfeature_apps = 'apps = false'\ni = first_section\nwhile i < len(snippet_lines):\n line = snippet_lines[i]\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", line.strip()):\n provider = snippet_lines[i:]\n break\n i += 1\nclean = []\nskip_codexapi = False\nskip_stale_mcp = False\nin_section = False\nin_features = False\nfeatures_seen = False\nfor line in original.splitlines():\n stripped = line.strip()\n if stale_mcp_re.match(stripped):\n skip_stale_mcp = True\n in_features = False\n continue\n if skip_stale_mcp and section_re.match(stripped):\n skip_stale_mcp = False\n if skip_stale_mcp:\n continue\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", stripped):\n skip_codexapi = True\n in_features = False\n continue\n if skip_codexapi and section_re.match(stripped):\n skip_codexapi = False\n if skip_codexapi:\n continue\n if section_re.match(stripped):\n in_section = True\n in_features = stripped == '[features]'\n features_seen = features_seen or in_features\n if not in_section:\n m = key_re.match(line)\n if m and m.group(1) in top_keys:\n continue\n if in_features:\n m = key_re.match(line)\n if m and m.group(1) == 'apps':\n continue\n clean.append(line)\nparts = []\nparts.extend(top)\nparts.append('')\ninserted_feature = False\nfor line in clean:\n parts.append(line)\n if line.strip() == '[features]':\n parts.append(feature_apps)\n inserted_feature = True\nif not features_seen:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(['[features]', feature_apps])\nif provider:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(provider)\npath.write_text('\\n'.join(line for line in parts if line is not None).rstrip() + '\\n')\nPY\nrm -f \"$CODEXAPI_CONFIG_SNIPPET\"\necho \"CodexAPI.pro is configured. Future macOS sessions can start with codex --search or codex resume --search.\"\ncodex --search",
"futureStartCommand": "codex\ncodex --search",
"startCommand": "set -e\nif ! command -v npm >/dev/null 2>&1; then\n if command -v apt-get >/dev/null 2>&1; then\n sudo apt-get update\n sudo apt-get install -y ca-certificates curl gnupg\n curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -\n sudo apt-get install -y nodejs git\n else\n echo \"Install Node.js LTS and npm first, then rerun this block.\" >&2\n exit 1\n fi\nfi\nnpm install -g @openai/codex@0.147.0\nCODEX_HOME_DIR=\"$HOME/.codex\"\nCONFIG_PATH=\"$CODEX_HOME_DIR/config.toml\"\nmkdir -p \"$CODEX_HOME_DIR\" 2>/dev/null || true\nif [ -e \"$CODEX_HOME_DIR\" ] && [ ! -w \"$CODEX_HOME_DIR\" ]; then\n echo \"Fixing ownership of $CODEX_HOME_DIR for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown -R \"$(id -u):$(id -g)\" \"$CODEX_HOME_DIR\"; fi\nfi\nif [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; then\n echo \"Fixing ownership of $CONFIG_PATH for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown \"$(id -u):$(id -g)\" \"$CONFIG_PATH\"; fi\nfi\nmkdir -p \"$CODEX_HOME_DIR\"\nif [ ! -w \"$CODEX_HOME_DIR\" ] || { [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; }; then\n echo \"Cannot write Codex config at $CONFIG_PATH. Run: sudo chown -R \\\"$(id -u):$(id -g)\\\" \\\"$CODEX_HOME_DIR\\\"\" >&2\n exit 1\nfi\nrm -rf \"$CODEX_HOME_DIR/cache/codex_apps_tools\" 2>/dev/null || true\nCODEXAPI_BACKUP_TS=\"$(date +%Y%m%d%H%M%S)\"\nCODEXAPI_CONFIG_SNIPPET=\"$(mktemp)\"\ncat > \"$CODEXAPI_CONFIG_SNIPPET\" <<'TOML'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\nTOML\npython3 - \"$CONFIG_PATH\" \"$CODEXAPI_CONFIG_SNIPPET\" <<'PY'\nimport os, re, shutil, sys\nfrom pathlib import Path\n\npath = Path(sys.argv[1]).expanduser()\nsnippet = Path(sys.argv[2]).read_text()\npath.parent.mkdir(parents=True, exist_ok=True)\nif path.exists():\n shutil.copy2(path, f\"{path}.backup.{os.environ.get('CODEXAPI_BACKUP_TS', 'manual')}\")\noriginal = path.read_text() if path.exists() else \"\"\ntop_keys = {\"model\", \"model_provider\", \"model_reasoning_effort\", \"approval_policy\", \"sandbox_mode\"}\nsection_re = re.compile(r\"^\\s*\\[[^\\]]+\\]\\s*$\")\nkey_re = re.compile(r\"^\\s*([A-Za-z0-9_-]+)\\s*=\")\nstale_mcp_re = re.compile(r\"^\\s*\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])\")\nsnippet_lines = snippet.strip().splitlines()\nfirst_section = next((i for i, line in enumerate(snippet_lines) if section_re.match(line.strip())), len(snippet_lines))\ntop = snippet_lines[:first_section]\nprovider = []\nfeature_apps = 'apps = false'\ni = first_section\nwhile i < len(snippet_lines):\n line = snippet_lines[i]\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", line.strip()):\n provider = snippet_lines[i:]\n break\n i += 1\nclean = []\nskip_codexapi = False\nskip_stale_mcp = False\nin_section = False\nin_features = False\nfeatures_seen = False\nfor line in original.splitlines():\n stripped = line.strip()\n if stale_mcp_re.match(stripped):\n skip_stale_mcp = True\n in_features = False\n continue\n if skip_stale_mcp and section_re.match(stripped):\n skip_stale_mcp = False\n if skip_stale_mcp:\n continue\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", stripped):\n skip_codexapi = True\n in_features = False\n continue\n if skip_codexapi and section_re.match(stripped):\n skip_codexapi = False\n if skip_codexapi:\n continue\n if section_re.match(stripped):\n in_section = True\n in_features = stripped == '[features]'\n features_seen = features_seen or in_features\n if not in_section:\n m = key_re.match(line)\n if m and m.group(1) in top_keys:\n continue\n if in_features:\n m = key_re.match(line)\n if m and m.group(1) == 'apps':\n continue\n clean.append(line)\nparts = []\nparts.extend(top)\nparts.append('')\ninserted_feature = False\nfor line in clean:\n parts.append(line)\n if line.strip() == '[features]':\n parts.append(feature_apps)\n inserted_feature = True\nif not features_seen:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(['[features]', feature_apps])\nif provider:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(provider)\npath.write_text('\\n'.join(line for line in parts if line is not None).rstrip() + '\\n')\nPY\nrm -f \"$CODEXAPI_CONFIG_SNIPPET\"\necho \"CodexAPI.pro is configured. Future sessions can start with codex or codex resume --search.\"\ncodex --search",
"execSmokeTestCommand": "codex --search exec --skip-git-repo-check \"Say hello from CodexAPI.pro.\"",
"loggedInOverrideCommand": "set -e\nif ! command -v npm >/dev/null 2>&1; then\n if command -v apt-get >/dev/null 2>&1; then\n sudo apt-get update\n sudo apt-get install -y ca-certificates curl gnupg\n curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -\n sudo apt-get install -y nodejs git\n else\n echo \"Install Node.js LTS and npm first, then rerun this block.\" >&2\n exit 1\n fi\nfi\nnpm install -g @openai/codex@0.147.0\nCODEX_HOME_DIR=\"$HOME/.codex\"\nCONFIG_PATH=\"$CODEX_HOME_DIR/config.toml\"\nmkdir -p \"$CODEX_HOME_DIR\" 2>/dev/null || true\nif [ -e \"$CODEX_HOME_DIR\" ] && [ ! -w \"$CODEX_HOME_DIR\" ]; then\n echo \"Fixing ownership of $CODEX_HOME_DIR for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown -R \"$(id -u):$(id -g)\" \"$CODEX_HOME_DIR\"; fi\nfi\nif [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; then\n echo \"Fixing ownership of $CONFIG_PATH for this user...\"\n if command -v sudo >/dev/null 2>&1; then sudo chown \"$(id -u):$(id -g)\" \"$CONFIG_PATH\"; fi\nfi\nmkdir -p \"$CODEX_HOME_DIR\"\nif [ ! -w \"$CODEX_HOME_DIR\" ] || { [ -e \"$CONFIG_PATH\" ] && [ ! -w \"$CONFIG_PATH\" ]; }; then\n echo \"Cannot write Codex config at $CONFIG_PATH. Run: sudo chown -R \\\"$(id -u):$(id -g)\\\" \\\"$CODEX_HOME_DIR\\\"\" >&2\n exit 1\nfi\nrm -rf \"$CODEX_HOME_DIR/cache/codex_apps_tools\" 2>/dev/null || true\nCODEXAPI_BACKUP_TS=\"$(date +%Y%m%d%H%M%S)\"\nCODEXAPI_CONFIG_SNIPPET=\"$(mktemp)\"\ncat > \"$CODEXAPI_CONFIG_SNIPPET\" <<'TOML'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\nTOML\npython3 - \"$CONFIG_PATH\" \"$CODEXAPI_CONFIG_SNIPPET\" <<'PY'\nimport os, re, shutil, sys\nfrom pathlib import Path\n\npath = Path(sys.argv[1]).expanduser()\nsnippet = Path(sys.argv[2]).read_text()\npath.parent.mkdir(parents=True, exist_ok=True)\nif path.exists():\n shutil.copy2(path, f\"{path}.backup.{os.environ.get('CODEXAPI_BACKUP_TS', 'manual')}\")\noriginal = path.read_text() if path.exists() else \"\"\ntop_keys = {\"model\", \"model_provider\", \"model_reasoning_effort\", \"approval_policy\", \"sandbox_mode\"}\nsection_re = re.compile(r\"^\\s*\\[[^\\]]+\\]\\s*$\")\nkey_re = re.compile(r\"^\\s*([A-Za-z0-9_-]+)\\s*=\")\nstale_mcp_re = re.compile(r\"^\\s*\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])\")\nsnippet_lines = snippet.strip().splitlines()\nfirst_section = next((i for i, line in enumerate(snippet_lines) if section_re.match(line.strip())), len(snippet_lines))\ntop = snippet_lines[:first_section]\nprovider = []\nfeature_apps = 'apps = false'\ni = first_section\nwhile i < len(snippet_lines):\n line = snippet_lines[i]\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", line.strip()):\n provider = snippet_lines[i:]\n break\n i += 1\nclean = []\nskip_codexapi = False\nskip_stale_mcp = False\nin_section = False\nin_features = False\nfeatures_seen = False\nfor line in original.splitlines():\n stripped = line.strip()\n if stale_mcp_re.match(stripped):\n skip_stale_mcp = True\n in_features = False\n continue\n if skip_stale_mcp and section_re.match(stripped):\n skip_stale_mcp = False\n if skip_stale_mcp:\n continue\n if re.match(r\"^\\[model_providers\\.codexapi\\]\\s*$\", stripped):\n skip_codexapi = True\n in_features = False\n continue\n if skip_codexapi and section_re.match(stripped):\n skip_codexapi = False\n if skip_codexapi:\n continue\n if section_re.match(stripped):\n in_section = True\n in_features = stripped == '[features]'\n features_seen = features_seen or in_features\n if not in_section:\n m = key_re.match(line)\n if m and m.group(1) in top_keys:\n continue\n if in_features:\n m = key_re.match(line)\n if m and m.group(1) == 'apps':\n continue\n clean.append(line)\nparts = []\nparts.extend(top)\nparts.append('')\ninserted_feature = False\nfor line in clean:\n parts.append(line)\n if line.strip() == '[features]':\n parts.append(feature_apps)\n inserted_feature = True\nif not features_seen:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(['[features]', feature_apps])\nif provider:\n if parts and parts[-1] != '':\n parts.append('')\n parts.extend(provider)\npath.write_text('\\n'.join(line for line in parts if line is not None).rstrip() + '\\n')\nPY\nrm -f \"$CODEXAPI_CONFIG_SNIPPET\"\necho \"CodexAPI.pro is configured. Future sessions can start with codex or codex resume --search.\"\ncodex --search",
"loggedInOverrideExecSmokeTestCommand": "codex --search exec --skip-git-repo-check \"Say hello from CodexAPI.pro.\"",
"resumeLastCommand": "codex resume --search\ncodex resume --last --search",
"windowsDependencyInstallCommand": "# Run PowerShell as Administrator for this dependency step.\nwinget source update\nwinget install --id OpenJS.NodeJS.LTS -e --accept-package-agreements --accept-source-agreements\nwinget install --id Git.Git -e --accept-package-agreements --accept-source-agreements\nSet-ExecutionPolicy -Scope CurrentUser RemoteSigned -Force\n# Close PowerShell, open a new PowerShell window, then run the verification step.",
"windowsVerifyDependenciesCommand": "node --version\nnpm --version\ngit --version",
"windowsCodexInstallCommand": "npm install -g @openai/codex@0.147.0\ncodex --version",
"windowsFullInstallCommand": "# Run PowerShell as Administrator for this dependency step.\nwinget source update\nwinget install --id OpenJS.NodeJS.LTS -e --accept-package-agreements --accept-source-agreements\nwinget install --id Git.Git -e --accept-package-agreements --accept-source-agreements\nSet-ExecutionPolicy -Scope CurrentUser RemoteSigned -Force\n# Close PowerShell, open a new PowerShell window, then run the verification step.\n\n# After reopening PowerShell:\nnode --version\nnpm --version\ngit --version\nnpm install -g @openai/codex@0.147.0\ncodex --version",
"windowsSetupAndStartCommand": "$ErrorActionPreference = \"Stop\"\nwinget source update\nif (-not (Get-Command node -ErrorAction SilentlyContinue)) { winget install --id OpenJS.NodeJS.LTS -e --accept-package-agreements --accept-source-agreements }\nif (-not (Get-Command git -ErrorAction SilentlyContinue)) { winget install --id Git.Git -e --accept-package-agreements --accept-source-agreements }\nnpm install -g @openai/codex@0.147.0\n$CodexHome = \"$env:USERPROFILE\\.codex\"\n$ConfigPath = Join-Path $CodexHome \"config.toml\"\nNew-Item -ItemType Directory -Force -Path $CodexHome | Out-Null\n$ConfigProbe = Join-Path $CodexHome \".codexapi-write-test\"\ntry {\n \"ok\" | Set-Content -Path $ConfigProbe -Encoding utf8 -Force\n Remove-Item $ConfigProbe -Force\n} catch {\n Write-Error \"Cannot write to $CodexHome. Open PowerShell as your normal Windows user, or fix folder ownership if this .codex folder was created by an Administrator shell.\"\n throw\n}\nif (Test-Path $ConfigPath) {\n Copy-Item $ConfigPath \"$ConfigPath.backup.$((Get-Date).ToString('yyyyMMddHHmmss'))\" -Force\n}\n$CodexAppsCache = Join-Path $CodexHome \"cache\\codex_apps_tools\"\nRemove-Item -Recurse -Force -ErrorAction SilentlyContinue $CodexAppsCache\n$CodexApiBackupStamp = (Get-Date).ToString('yyyyMMddHHmmss')\n$CodexApiConfigSnippet = @'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\n'@\nif (Test-Path $ConfigPath) { Copy-Item $ConfigPath \"$ConfigPath.backup.$CodexApiBackupStamp\" -Force }\n$ExistingConfig = if (Test-Path $ConfigPath) { Get-Content $ConfigPath -Raw } else { \"\" }\n$Lines = @()\n$SkipCodexApi = $false\n$SkipStaleMcp = $false\n$InSection = $false\n$InFeatures = $false\n$FeaturesSeen = $false\nforeach ($Line in ($ExistingConfig -split \"`r?`n\")) {\n $Trimmed = $Line.Trim()\n if ($Trimmed -match '^\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])') { $SkipStaleMcp = $true; $InFeatures = $false; continue }\n if ($SkipStaleMcp -and $Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $SkipStaleMcp = $false }\n if ($SkipStaleMcp) { continue }\n if ($Trimmed -match '^\\[model_providers\\.codexapi\\]\\s*$') { $SkipCodexApi = $true; $InFeatures = $false; continue }\n if ($SkipCodexApi -and $Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $SkipCodexApi = $false }\n if ($SkipCodexApi) { continue }\n if ($Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $InSection = $true; $InFeatures = ($Trimmed -eq '[features]'); if ($InFeatures) { $FeaturesSeen = $true } }\n if (-not $InSection -and $Trimmed -match '^(model|model_provider|model_reasoning_effort|approval_policy|sandbox_mode)\\s*=') { continue }\n if ($InFeatures -and $Trimmed -match '^apps\\s*=') { continue }\n if ($Line.Trim().Length -gt 0) { $Lines += $Line }\n}\n$SnippetLines = $CodexApiConfigSnippet.Trim() -split \"`r?`n\"\n$FirstSection = $SnippetLines.Count\nfor ($i = 0; $i -lt $SnippetLines.Count; $i++) { if ($SnippetLines[$i].Trim() -match \"^\\[[^\\]]+\\]\\s*$\") { $FirstSection = $i; break } }\n$Top = @($SnippetLines[0..($FirstSection - 1)]) | Where-Object { $_ -ne $null }\n$ProviderStart = -1\nfor ($i = 0; $i -lt $SnippetLines.Count; $i++) { if ($SnippetLines[$i].Trim() -match \"^\\[model_providers\\.codexapi\\]\\s*$\") { $ProviderStart = $i; break } }\n$Provider = if ($ProviderStart -ge 0) { @($SnippetLines[$ProviderStart..($SnippetLines.Count - 1)]) } else { @() }\n$Out = @()\n$Out += $Top\n$Out += ''\n$InsertedFeatures = $false\nforeach ($Line in $Lines) { $Out += $Line; if ($Line.Trim() -eq '[features]') { $Out += 'apps = false'; $InsertedFeatures = $true } }\nif (-not $FeaturesSeen) { $Out += ''; $Out += '[features]'; $Out += 'apps = false' }\n$Out += ''\n$Out += $Provider\n($Out -join \"`n\").Trim() + \"`n\" | Set-Content -Path $ConfigPath -Encoding UTF8\nWrite-Host \"CodexAPI.pro is configured. Future sessions can start with codex or codex resume --search.\"\ncodex --search",
"windowsSetupCommand": "$ErrorActionPreference = \"Stop\"\nwinget source update\nif (-not (Get-Command node -ErrorAction SilentlyContinue)) { winget install --id OpenJS.NodeJS.LTS -e --accept-package-agreements --accept-source-agreements }\nif (-not (Get-Command git -ErrorAction SilentlyContinue)) { winget install --id Git.Git -e --accept-package-agreements --accept-source-agreements }\nnpm install -g @openai/codex@0.147.0\n$CodexHome = \"$env:USERPROFILE\\.codex\"\n$ConfigPath = Join-Path $CodexHome \"config.toml\"\nNew-Item -ItemType Directory -Force -Path $CodexHome | Out-Null\n$ConfigProbe = Join-Path $CodexHome \".codexapi-write-test\"\ntry {\n \"ok\" | Set-Content -Path $ConfigProbe -Encoding utf8 -Force\n Remove-Item $ConfigProbe -Force\n} catch {\n Write-Error \"Cannot write to $CodexHome. Open PowerShell as your normal Windows user, or fix folder ownership if this .codex folder was created by an Administrator shell.\"\n throw\n}\nif (Test-Path $ConfigPath) {\n Copy-Item $ConfigPath \"$ConfigPath.backup.$((Get-Date).ToString('yyyyMMddHHmmss'))\" -Force\n}\n$CodexAppsCache = Join-Path $CodexHome \"cache\\codex_apps_tools\"\nRemove-Item -Recurse -Force -ErrorAction SilentlyContinue $CodexAppsCache\n$CodexApiBackupStamp = (Get-Date).ToString('yyyyMMddHHmmss')\n$CodexApiConfigSnippet = @'\nmodel = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nexperimental_bearer_token = \"<CODEXAPI_API_KEY>\"\nwire_api = \"responses\"\nsupports_websockets = false\n'@\nif (Test-Path $ConfigPath) { Copy-Item $ConfigPath \"$ConfigPath.backup.$CodexApiBackupStamp\" -Force }\n$ExistingConfig = if (Test-Path $ConfigPath) { Get-Content $ConfigPath -Raw } else { \"\" }\n$Lines = @()\n$SkipCodexApi = $false\n$SkipStaleMcp = $false\n$InSection = $false\n$InFeatures = $false\n$FeaturesSeen = $false\nforeach ($Line in ($ExistingConfig -split \"`r?`n\")) {\n $Trimmed = $Line.Trim()\n if ($Trimmed -match '^\\[mcp_servers\\.(codex_apps|memories|blender)(?:\\.|\\])') { $SkipStaleMcp = $true; $InFeatures = $false; continue }\n if ($SkipStaleMcp -and $Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $SkipStaleMcp = $false }\n if ($SkipStaleMcp) { continue }\n if ($Trimmed -match '^\\[model_providers\\.codexapi\\]\\s*$') { $SkipCodexApi = $true; $InFeatures = $false; continue }\n if ($SkipCodexApi -and $Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $SkipCodexApi = $false }\n if ($SkipCodexApi) { continue }\n if ($Trimmed -match '^\\[[^\\]]+\\]\\s*$') { $InSection = $true; $InFeatures = ($Trimmed -eq '[features]'); if ($InFeatures) { $FeaturesSeen = $true } }\n if (-not $InSection -and $Trimmed -match '^(model|model_provider|model_reasoning_effort|approval_policy|sandbox_mode)\\s*=') { continue }\n if ($InFeatures -and $Trimmed -match '^apps\\s*=') { continue }\n if ($Line.Trim().Length -gt 0) { $Lines += $Line }\n}\n$SnippetLines = $CodexApiConfigSnippet.Trim() -split \"`r?`n\"\n$FirstSection = $SnippetLines.Count\nfor ($i = 0; $i -lt $SnippetLines.Count; $i++) { if ($SnippetLines[$i].Trim() -match \"^\\[[^\\]]+\\]\\s*$\") { $FirstSection = $i; break } }\n$Top = @($SnippetLines[0..($FirstSection - 1)]) | Where-Object { $_ -ne $null }\n$ProviderStart = -1\nfor ($i = 0; $i -lt $SnippetLines.Count; $i++) { if ($SnippetLines[$i].Trim() -match \"^\\[model_providers\\.codexapi\\]\\s*$\") { $ProviderStart = $i; break } }\n$Provider = if ($ProviderStart -ge 0) { @($SnippetLines[$ProviderStart..($SnippetLines.Count - 1)]) } else { @() }\n$Out = @()\n$Out += $Top\n$Out += ''\n$InsertedFeatures = $false\nforeach ($Line in $Lines) { $Out += $Line; if ($Line.Trim() -eq '[features]') { $Out += 'apps = false'; $InsertedFeatures = $true } }\nif (-not $FeaturesSeen) { $Out += ''; $Out += '[features]'; $Out += 'apps = false' }\n$Out += ''\n$Out += $Provider\n($Out -join \"`n\").Trim() + \"`n\" | Set-Content -Path $ConfigPath -Encoding UTF8\nWrite-Host \"CodexAPI.pro is configured. Future sessions can start with codex or codex resume --search.\"\ncodex --search",
"windowsStartCommand": "codex\ncodex --search",
"windowsResumeLastCommand": "codex resume --search\ncodex resume --last --search",
"windowsExecSmokeTestCommand": "codex --search exec --skip-git-repo-check \"Say hello from CodexAPI.pro.\"",
"macosStartCommand": "codex\ncodex --search",
"macosResumeLastCommand": "codex resume --search\ncodex resume --last --search",
"macosExecSmokeTestCommand": "codex --search exec --skip-git-repo-check \"Say hello from CodexAPI.pro.\"",
"configToml": "model = \"gpt-5.6\"\nmodel_provider = \"codexapi\"\nmodel_reasoning_effort = \"xhigh\"\napproval_policy = \"never\"\nsandbox_mode = \"danger-full-access\"\n\n[features]\napps = false\n\n[model_providers.codexapi]\nname = \"CodexAPI.pro\"\nbase_url = \"https://api-canada.codexapi.pro/v1\"\nenv_key = \"CODEXAPI_CODEX_API_KEY\"\nwire_api = \"responses\"\nsupports_websockets = false\n",
"clientModelLabel": "Deepseek v4 Budget",
"displayModel": "Deepseek v4 Budget",
"modelDisplayName": "Deepseek v4 Budget"
}
Windows users must use PowerShell syntax, not Bash exports. The live /api/v1/cli/public-codex payload includes a complete PowerShell setup block that installs dependencies when needed, writes %USERPROFILE%\.codex\config.toml, saves the wallet username as the provider bearer token, and starts codex --search.
gpt-5.6; managed destination alias: power-aineverdanger-full-accesscodex app-server over stdio with the required initialize then initialized handshake.0.135.0 keeps legacy turn-level sandboxPolicy compatibility, while newer clients can send permissions / permissionProfile profile selections through the stable project endpoints or protected raw app-server RPC.experimentalApi during initialize, so the new /permissions Full Access client toggle can send permission profiles without being rejected by app-server.GET /api/v1/permissions publishes the Full Access and workspace profile payloads; GET /api/v1/skills lists the root Codex skills available to API-backed sessions.thread/goal/*, hooks/list, and modelProvider/capabilities/read are reachable through the protected raw RPC adapter. The stable browser-agent endpoints continue to stream the core thread, turn, item, and approval lifecycle.GET /api/v1/agent/status to inspect live runtime and defaults.POST /api/v1/projects to create a durable project workspace.POST /api/v1/projects/{project_id}/open to create or resume the workspace thread.POST /api/v1/projects/{project_id}/turns to start work.GET /api/v1/projects/{project_id}/events for SSE notifications.GET /api/v1/billing/token-usage to render wallet token transactions and daily usage graphs for the signed-in user.GET /api/v1/share-credit and POST /api/v1/share-credit/claim power the one-time $10 CodexAPI.pro share-credit dashboard offer.Each managed project_id maps to one stable workspace directory. When the same user returns to that project, the API resumes the latest Codex thread for that workspace instead of creating a fresh conversation.
Project-scoped approval handling stays explicit:
GET /api/v1/projects/{project_id}/approvals lists pending approval requests for the project’s latest thread.POST /api/v1/projects/{project_id}/approvals/{request_id}/resolve resolves the approval. An empty JSON body now defaults to {"decision":"accept"} for the current command and file-change approval flows.POST /api/v1/projects/{project_id}/turns/{turn_id}/interrupt interrupts a running turn.This catalogue is generated from the live FastAPI route table and filtered to customer-facing endpoints. Public calls need no bearer token, and API calls accept the System Token, customer username, or a user-created API key.
| Method | Path | Access | Tags | Summary |
|---|---|---|---|---|
GET | /api/core/releases/current | api | releases | Read the current synced stable Codex release |
GET | /api/models | api | rpc | List visible Codex models |
POST | /api/projects/open | api | threads | Open a project by cwd, resuming the latest matching thread when present |
GET | /api/status/regions | public | system | Regional API availability |
GET | /api/threads | api | threads | List Codex threads |
POST | /api/threads | api | threads | Start a new thread |
GET | /api/threads/{thread_id} | api | threads | Read a thread by id |
POST | /api/threads/{thread_id}/resume | api | threads | Resume an existing thread |
POST | /api/turns | api | turns | Start a new turn on a thread |
POST | /api/turns/{turn_id}/interrupt | api | turns | Interrupt an active turn |
GET | /api/v1/agent/status | api | agent | Read the managed Codex account state and default coding-agent configuration |
GET | /api/v1/auth/google/callback | public | auth | Complete Google sign-up or sign-in for a CodexAPI.pro wallet account |
GET | /api/v1/auth/google/start | public | auth | Start Google sign-up or sign-in for a CodexAPI.pro wallet account |
GET | /api/v1/auth/human-check | public | auth | Create a self-hosted signup human-verification challenge |
POST | /api/v1/auth/login | public | auth | Authenticate a CodexAPI.pro CLI user and issue a wallet-linked API key |
POST | /api/v1/auth/password-reset/confirm | public | auth | Set a new dashboard password from a reset link |
POST | /api/v1/auth/password-reset/request | public | auth | Email a short-lived dashboard password reset link |
GET | /api/v1/auth/sso | public | auth | Open the customer dashboard from a signed notification link |
POST | /api/v1/auth/web-login | public | auth | Authenticate a CodexAPI.pro dashboard user |
POST | /api/v1/auth/web-login/2fa | public | auth | Complete CodexAPI.pro dashboard login with a Google Authenticator code |
GET | /api/v1/billing/currency-estimates | api | billing | Read estimated local-currency conversions while checkout remains USD |
GET | /api/v1/billing/token-usage | api | billing | Read token usage transactions and daily spend for the current wallet |
POST | /api/v1/cash-wallet/paymento/checkout | api | billing | Create a Paymento crypto checkout to load real-money Cash Wallet balance |
POST | /api/v1/cash-wallet/stripe/checkout | api | billing | Create a Stripe Checkout Session to load real-money Cash Wallet balance |
POST | /api/v1/cash-wallet/stripe/confirm | api | billing | Confirm a paid Stripe Checkout Session and reconcile Cash Wallet balance |
POST | /api/v1/cash-wallet/token-purchase | api | billing | Use Cash Wallet balance to buy a Token Wallet top-up package |
POST | /api/v1/cash-wallet/unlimited-purchase | api | billing | Use Cash Wallet balance to buy an Unlimited Coding plan |
POST | /api/v1/claude-desktop/object-workspace | api | desktop | Ensure the current customer's private desktop object workspace |
POST | /api/v1/claude-desktop/object-workspace/projects | api | desktop | Create a private project folder in the current customer's desktop workspace |
DELETE | /api/v1/claude-desktop/object-workspace/projects/{project_id} | api | desktop | Delete the current customer's private desktop project marker |
POST | /api/v1/claude-desktop/object-workspace/repositories/{repository_name} | api | desktop | Store an authenticated customer's repository archive in their private desktop workspace |
GET | /api/v1/claude-desktop/push | api | desktop | List persistent Claude Desktop service messages |
POST | /api/v1/claude-desktop/push/{message_key}/dismiss | api | desktop | Dismiss one Claude Desktop service message |
GET | /api/v1/claude-desktop/sync | api | desktop | Read synchronized Claude Desktop conversation history |
PUT | /api/v1/claude-desktop/sync | api | desktop | Synchronize Claude Desktop conversation history |
GET | /api/v1/claudecodex/version | public | system | Read the required CodexAPI.pro claudecodex launcher version |
GET | /api/v1/cli/version | public | system | Read the current CodexAPI.pro Codex CLI release metadata |
GET | /api/v1/codexclaude/version | public | system | Read the required CodexAPI.pro codexclaude launcher version |
GET | /api/v1/customer-engagement | api | dashboard | Read promotion history, eligibility, and notification preferences |
PUT | /api/v1/customer-engagement | api | dashboard | Save promotion, reminder, timezone, and motion preferences |
POST | /api/v1/customer/register | public | auth | Create a CodexAPI.pro customer account and issue a wallet-linked API key |
GET | /api/v1/daily-checkin | api | billing | Read the current wallet's Daily Check-in reward status |
POST | /api/v1/daily-checkin/claim | api | billing | Claim today's Daily Check-in wallet reward |
GET | /api/v1/desktop-chat/bootstrap | api | desktop-chat | Load CodexAPI.pro Desktop Chat conversations, models, and free daily quota |
POST | /api/v1/desktop-chat/conversations | api | desktop-chat | Create a CodexAPI.pro Desktop Chat conversation |
GET | /api/v1/desktop-chat/conversations | api | desktop-chat | List CodexAPI.pro Desktop Chat conversations |
DELETE | /api/v1/desktop-chat/conversations/{conversation_id} | api | desktop-chat | Delete a CodexAPI.pro Desktop Chat conversation |
GET | /api/v1/desktop-chat/conversations/{conversation_id}/messages | api | desktop-chat | Read CodexAPI.pro Desktop Chat conversation messages |
POST | /api/v1/desktop-chat/conversations/{conversation_id}/messages | api | desktop-chat | Send a CodexAPI.pro Desktop Chat prompt with saved conversation context |
GET | /api/v1/desktop-chat/messages/{message_id}/research.pdf | api | desktop-chat | Download a completed Desktop Chat Deep Research analysis as a PDF |
GET | /api/v1/desktop-chat/shoutbox/bootstrap | api | desktop-chat | Load the shared CodexAPI.pro Desktop Chat Shoutbox |
GET | /api/v1/desktop-chat/shoutbox/messages | api | desktop-chat | List shared CodexAPI.pro Desktop Chat Shoutbox messages |
POST | /api/v1/desktop-chat/shoutbox/messages | api | desktop-chat | Send a shared CodexAPI.pro Desktop Chat Shoutbox message |
POST | /api/v1/desktop-chat/shoutbox/profile | api | desktop-chat | Set the user's shared Desktop Chat Shoutbox username |
GET | /api/v1/desktop/bootstrap | api | desktop | Verify a CodexAPI.pro token and return Windows desktop setup payloads |
POST | /api/v1/desktop/bug-report | api | desktop | Send a customer desktop bug report to CodexAPI.pro support |
GET | /api/v1/desktop/coder/projects | api | desktop | List Windows Desktop Coding Mode projects and managed databases |
POST | /api/v1/desktop/coder/projects | api | desktop | Create or resume a Windows Desktop Coding Mode project |
POST | /api/v1/desktop/coder/projects/purchase-slot | api | desktop | Buy one additional Windows Desktop Coding Mode project slot from Token Wallet credit |
DELETE | /api/v1/desktop/coder/projects/{project_name} | api | desktop | Delete a Windows Desktop Coding Mode project and its managed database |
GET | /api/v1/desktop/coding-session | api | desktop | Load the saved CodexAPI.pro Desktop coding conversation history |
PUT | /api/v1/desktop/coding-session | api | desktop | Persist CodexAPI.pro Desktop coding conversation history |
POST | /api/v1/desktop/presence | api | desktop | Record a live Desktop Setup Client heartbeat |
POST | /api/v1/gumroad/register | public | auth | Create a Gumroad.com buyer account and load $200 Token Wallet credit |
GET | /api/v1/me | api | auth | Read the current CodexAPI.pro customer wallet and CLI configuration |
POST | /api/v1/me/2fa/disable | api | auth | Disable Google Authenticator 2FA for the current dashboard user |
POST | /api/v1/me/2fa/enable | api | auth | Enable Google Authenticator 2FA after verifying the setup code |
POST | /api/v1/me/2fa/setup | api | auth | Start Google Authenticator 2FA setup for the current dashboard user |
GET | /api/v1/me/api-key-alerts | api | auth | List User API Key security and usage alerts |
POST | /api/v1/me/api-key-alerts/{event_id}/acknowledge | api | auth | Acknowledge a User API Key alert |
POST | /api/v1/me/api-keys | api | auth | Create a wallet-linked User API Key for the current customer |
GET | /api/v1/me/api-keys | api | auth | List the current customer's System Token and wallet-linked User API Keys |
DELETE | /api/v1/me/api-keys/{key_id} | api | auth | Revoke one of the current customer's User API Keys |
PATCH | /api/v1/me/api-keys/{key_id} | api | auth | Update a customer User API Key policy |
GET | /api/v1/me/api-keys/{key_id}/health | api | auth | Run a non-billable User API Key integration health check |
POST | /api/v1/me/api-keys/{key_id}/replace | api | auth | Replace a customer User API Key immediately |
GET | /api/v1/me/api-keys/{key_id}/usage | api | auth | Read usage for one customer User API Key |
POST | /api/v1/me/api-token/rotate | api | auth | Rotate the current customer's Codex API username/token once every 24 hours |
POST | /api/v1/me/edge-region | api | auth | Set the current customer's preferred London or Chicago API server |
POST | /api/v1/me/email | api | auth | Save the required customer email address for the current CodexAPI.pro wallet |
POST | /api/v1/me/password | api | auth | Change the current CodexAPI.pro dashboard password |
POST | /api/v1/me/profile-name | api | auth | Save the customer profile first name and surname |
POST | /api/v1/me/profile-name/dismiss | api | auth | Record that the customer skipped the profile name modal |
POST | /api/v1/me/sso-link | api | auth | Create a short-lived one-click dashboard sign-on link for the current customer |
GET | /api/v1/messages | api | auth | List the current customer's inbox messages |
POST | /api/v1/messages/{message_id}/read | api | auth | Mark a customer inbox message read |
GET | /api/v1/permissions | api | agent | Read Codex permission profile presets for API clients |
POST | /api/v1/projects | api | projects | Create a managed project workspace for a web coding session |
GET | /api/v1/projects | api | projects | List managed isolated project workspaces |
GET | /api/v1/projects/{project_id} | api | projects | Read managed project metadata and its latest Codex thread summary |
GET | /api/v1/projects/{project_id}/approvals | api | agent | List pending approval requests for the latest managed project thread |
POST | /api/v1/projects/{project_id}/approvals/{request_id}/resolve | api | agent | Resolve a pending project-scoped approval request |
GET | /api/v1/projects/{project_id}/events | api | agent | Stream project-scoped Codex notifications over SSE |
GET | /api/v1/projects/{project_id}/files/content | api | projects | Read a file from a managed project workspace |
PUT | /api/v1/projects/{project_id}/files/content | api | projects | Write a file inside a managed project workspace |
GET | /api/v1/projects/{project_id}/files/tree | api | projects | List files inside a managed project workspace |
POST | /api/v1/projects/{project_id}/open | api | agent | Open or resume a managed project and optionally start an initial turn |
GET | /api/v1/projects/{project_id}/state | api | agent | Read project metadata, latest thread state, and pending project-scoped approvals |
GET | /api/v1/projects/{project_id}/thread | api | agent | Read the latest Codex thread for a managed project |
POST | /api/v1/projects/{project_id}/turns | api | agent | Start a project-scoped Codex turn using the web-coding defaults |
POST | /api/v1/projects/{project_id}/turns/{turn_id}/interrupt | api | agent | Interrupt an active turn for a managed project |
GET | /api/v1/purchase-preferences | api | billing | Read Deposit, low-balance, and business receipt preferences |
PUT | /api/v1/purchase-preferences | api | billing | Save Deposit, low-balance, and business receipt preferences |
GET | /api/v1/raffle | api | billing | Read the current wallet's worldwide coding raffle status |
POST | /api/v1/reddit/conversion | public | analytics | Send a server-side Reddit Conversions API website event |
GET | /api/v1/referral | api | billing | Read the current CodexAPI.pro VIP Referral Club and Cash Wallet status |
POST | /api/v1/setup/health-check | api | auth | Run a non-billable account and setup readiness check |
GET | /api/v1/share-credit | api | billing | Read the one-time CodexAPI.pro share-credit offer for the current wallet |
POST | /api/v1/share-credit/claim | api | billing | Claim the one-time CodexAPI.pro share credit after sharing the public site |
GET | /api/v1/skills | api | agent | List Codex skills available to API-backed Codex sessions |
GET | /api/v1/spin-wheel | api | billing | Read the current customer's Spin the Wheel promotion status |
POST | /api/v1/spin-wheel/spin | api | billing | Use the current customer's single Spin the Wheel entry |
GET | /api/v1/status/regions | public | system | Regional API availability |
POST | /api/v1/stripe/webhook | public | billing | Receive Stripe wallet payment events |
GET | /api/v1/telegram/google/callback | public | auth | Complete Telegram Google account linking |
GET | /api/v1/telegram/google/start | public | auth | Start Google sign-in for linking an existing CodexAPI.pro account to Telegram |
POST | /api/v1/telegram/webhook | public | auth | Receive Telegram Bot API webhook updates for dashboard actions |
GET | /api/v1/toolbox | api | auth | Read the current customer Toolbox settings |
POST | /api/v1/toolbox | api | auth | Update the current customer Toolbox settings |
GET | /api/v1/unlimited-coding/plans | api | billing | List currently available Unlimited Coding plans |
GET | /api/v1/vip | public | auth | Read the current customer's VIP Priority server access |
POST | /api/v1/wallet/auto-topup | api | billing | Configure automatic wallet top-up for the current CodexAPI.pro user |
POST | /api/v1/wallet/paymento/checkout | api | billing | Create a crypto checkout |
GET | /api/v1/wallet/paymento/options | api | billing | List crypto checkout options |
GET | /api/v1/wallet/paymento/orders/{order_id} | api | billing | Check a crypto order |
GET | /api/v1/wallet/paymento/orders/{order_id}/receipt.pdf | api | billing | Download a customer-owned crypto payment receipt |
GET | /api/v1/wallet/paymento/refund-addresses | api | billing | List saved refund addresses |
POST | /api/v1/wallet/paymento/refund-addresses | api | billing | Save a refund address |
DELETE | /api/v1/wallet/paymento/refund-addresses/{address_id} | api | billing | Delete a refund address |
GET | /api/v1/wallet/payments | api | billing | List Stripe wallet payments and receipt availability |
GET | /api/v1/wallet/status | api | billing | Read a lightweight wallet balance snapshot for CLI launchers |
POST | /api/v1/wallet/stripe/checkout | api | billing | Create a Stripe Checkout Session for a CodexAPI.pro wallet credit pack |
POST | /api/v1/wallet/stripe/confirm | api | billing | Confirm a paid Stripe Checkout Session and reconcile wallet credit |
POST | /api/v1/wallet/top-up | api | billing | Load credit onto the current CodexAPI.pro wallet after a plan payment |
POST | /api/v1/wallet/topup-discount | api | billing | Validate a user-scoped top-up bonus code |
POST | /api/v1/wallet/topupemail-session-discount | api | billing | Issue a time-boxed top-up email discount |
POST | /v1/chat/completions | api | openai-compatible | Create an OpenAI-compatible Chat Completion using the active CodexAPI.pro routing policy |
GET | /v1/chat/completions | api | openai-compatible | List locally cached Chat Completions for this bearer |
DELETE | /v1/chat/completions/{completion_id} | api | openai-compatible | Delete a locally cached Chat Completion |
GET | /v1/chat/completions/{completion_id} | api | openai-compatible | Retrieve a locally cached Chat Completion |
PATCH | /v1/chat/completions/{completion_id} | api | openai-compatible | Update metadata for a locally cached Chat Completion |
POST | /v1/completions | api | openai-compatible | Create a legacy OpenAI-compatible text completion using the active Responses route |
POST | /v1/messages | api | anthropic-compatible | Proxy Claude Code CLI Messages API traffic through CodexAPI.pro wallet billing |
POST | /v1/messages/{subpath:path} | api | anthropic-compatible | Proxy Claude Code CLI auxiliary Messages API traffic |
GET | /v1/models | api | openai-compatible | List CodexAPI.pro models for stock public Codex CLI |
GET | /v1/models/{model_id:path} | api | openai-compatible | Retrieve one CodexAPI.pro model descriptor |
POST | /v1/responses | api | openai-compatible | Proxy stock public Codex CLI Responses API traffic through CodexAPI.pro wallet billing |
POST | /v1/responses/count_tokens | api | openai-compatible | Estimate input tokens for an OpenAI-compatible Responses payload |
DELETE | /v1/responses/{response_id} | api | openai-compatible | Delete a locally cached OpenAI-compatible Responses object |
GET | /v1/responses/{response_id} | api | openai-compatible | Retrieve a locally cached OpenAI-compatible Responses object |
POST | /v1/responses/{response_id}/cancel | api | openai-compatible | Cancel a Responses request if it is still pending |
POST | /v1/responses/{response_id}/compact | api | openai-compatible | Return a compacted summary of a locally cached Responses object |
GET | /v1/responses/{response_id}/input_items | api | openai-compatible | List input items captured for a locally cached Responses object |