Troubleshooting · opencode

opencode API Key Not Picked Up — auth and {env} Placeholders

opencode authenticates a custom provider through options.apiKey, usually an {env:...} placeholder. Why the variable silently resolves empty and requests fail with 401.

What you see

opencode 401 unauthorized

Why it happens

  • The {env:NAME} placeholder names a variable that is not set in the environment opencode launched from — it resolves empty and the provider sees no key.
  • The variable is exported in one shell but opencode starts from another: a desktop launcher, another terminal, a multiplexer pane.
  • The key is pasted literally into opencode.json with surrounding whitespace, or it belongs to a different endpoint than the baseURL.

How to fix it

  • Export the exact variable named in the placeholder in the same shell, then start opencode from that shell.
  • Confirm the pair with curl: the baseURL from the config plus the key from the variable must succeed outside opencode first.
  • Prefer the {env:...} form over pasting the key into the file — it keeps the secret out of dotfiles and version control.

Key via environment, not in the file

export APITOKEN_API_KEY="sk-pool-•••"
opencode

# opencode.json references it as:
#   "apiKey": "{env:APITOKEN_API_KEY}"

Related searches

  • opencode api key not working
  • opencode auth error custom provider

FAQ

Why does opencode send no API key even though opencode.json names one?+
An {env:NAME} placeholder resolves at startup from opencode's own environment. If that shell never exported the variable, the key is empty.
Is it safe to paste the key directly into opencode.json?+
It works, but the env placeholder is the better habit: config files travel into backups and repositories, and a pasted key travels with them.
How do I check which half is broken, the key or the URL?+
curl the baseURL with the key by hand. 401 means the key/endpoint pair; connection errors mean the URL or network.

Skip the broken setup

apiToken.sale serves the standard Anthropic API — same models, same SDKs, one prepaid balance. Point your tool's base URL at it, and the config on this page works as written.