The API key authenticates your CI against the CodeCharter portal. It is just as sensitive as a production database password and should be treated accordingly.
Where keys belong
| CI system | Storage location |
|---|---|
| GitHub Actions | Repository Secrets or Org Secrets |
| GitLab CI | Project Variables (Protected, Masked) |
| Azure DevOps | Library Variable Groups, secret-locked |
| Bitbucket Pipelines | Repository Variables, Secured |
| TeamCity | Project Parameter, type "Password" |
| Jenkins | Credentials Manager, "Secret text" |
Whatever the storage location, expose the secret to the build as the
CODECHARTER_API_KEY environment variable — that is the variable the CLI reads
automatically.
Where keys do NOT belong
- Never commit them to the repo. Not even "just for a quick test". Git history is permanent — a key that was once exposed is burned.
- Not in logs. If a script contains
echo "Key: $CODECHARTER_API_KEY", it will appear in the build log and potentially in artifacts and security scans. - Not in
.envfiles that you might accidentally share in backups, Slack threads, or wikis.
Masking in CI logs
Most CI systems automatically mask secret variables in logs when they are marked as secrets. Still, watch out for:
# Bad — the token ends up as a URL parameter in the log
curl "https://example.com/?token=$CODECHARTER_API_KEY"
# Better — as a header, which is not logged
curl -H "Authorization: Bearer $CODECHARTER_API_KEY" https://example.com/
Rotating a key
If a key is compromised or a team member leaves who may have seen it in plain text, replace it like this:
- Generate a new key in the portal under API Keys.
- Store the new key in the CI system (update the secret variable).
- Run the CI once and confirm everything is green.
- Revoke the old key in the portal.
Multiple keys can be active at the same time, so you can take your time with steps 2 and 3 before revoking the old one in step 4. Revocation is permanent — a revoked key cannot be reactivated.
One caveat: the CLI caches the short-lived license it obtains with the key for up to 24 hours per runner. A green run in step 3 may therefore still be running on a license obtained with the old key, and runs can keep succeeding for up to 24 hours after you revoke the old key.
One key per repo or per team?
The default recommendation is one key per repository (or per CI job family). This limits the blast radius if a key is compromised: a leaked key for one repo does not expose the pipelines of every other repo.
- One key per repo is the least-privilege default. If one repo's secret is exposed, the others remain unaffected.
- One shared key per team or job family is a convenience trade-off, acceptable when all repos carry the same trust level and you have rotation automation in place. Never share a key between a public repo and a private one.
- Not one key per developer. Keys belong to CI jobs, not to individuals.
- Meaningful names. You can give a key a name in the portal.
acme-web-ciis good,prod-keyis okay,keyis not helpful during an audit.
Key compromised — what to do
- Revoke the key immediately in the portal.
- Generate a new key.
- Update the CI secret variable.
- Check the key's Last used timestamp on the API Keys page for unexpected recent activity.
- If the key was publicly exposed (e.g. in a PR): GitHub Secret Scanning typically fires automatically. Revoking the key in the portal is the only way to cut off its access — note that license tokens already issued with the key remain valid for up to 24 hours and cannot be recalled.
Lifecycle
In the portal you can set a lifetime per key: 30 days, 90 days, 1 year (the default), or never. After expiry the key is automatically deactivated.
A pipeline that is already running when the key expires completes without
interruption: the CLI checks the license once at the start of a command, exchanging
the key for a short-lived license that is valid for 24 hours. Because this license is
cached per runner, new runs started after expiry may keep working for up to 24 hours
before they fail with exit code 6 when the CLI can no longer obtain a license; on
ephemeral runners without a cache they fail right away. Set up key rotation before
expiry to avoid unplanned CI failures.
Useful for temporary keys, for example for an external consulting firm that needs temporary access to your CI.
See Managing API keys.