Protecting your API keys
A payment key in a git repository is a bank card in a letterbox. The rules, and what to do when it has already happened.
Your API key authorises everything its permissions cover: creating payment links, reading your transactions, issuing refunds. There is no second factor and no confirmation — so grant each key only the permissions it actually needs. It is a secret in the full sense of the word.
The five rules
A key lives on a server, never in a browser. Not in client-side JavaScript, not in a mobile app — an .apk file decompiles in seconds. If your front end needs to trigger a payment, it calls *your* backend, which calls ours.
A key lives in an environment variable or a vault, never in code. Not even in a private repository: repositories change status, collaborators change employers, backups get copied.
A test key and a production key are two different things. The prefix says so — chari_sk_test_ versus chari_sk_live_ — and the environment is determined by the key itself. That is precisely what makes it impossible to send a test call to production by mistake.
A key does not get written to a log. Beware of error trackers and observability tools that capture HTTP headers: that is the most common leak, and the quietest, because the secret ends up with a third party without anyone ever deciding it should.
A key is not shared over messaging. Not by email, not on Slack, not on WhatsApp. Those channels retain, index and back up.
What actually happens
The scenario we see most is not an attack. It is a developer in a hurry who puts the key in a config file "just to test", forgets, and pushes. The repository is private, so "it's fine". Six months later it goes public, or a contractor gets access, or a backup lands somewhere else.
The second most common scenario is the .env file committed on day one of the project, before anyone had written the .gitignore.
If a key has leaked
In order, and without waiting:
- 1Revoke it. A compromised key is not a key to watch, it is a key to delete. Create its replacement first if you want to avoid an outage, but do not delay the revocation.
- 2Treat the whole history as exposed. Removing the file from the repository is not enough: it stays in the git history, and history gets cloned.
- 3Look at what was done with it. The operations log tells you what was created, read and refunded, and when.
- 4Fix the cause. A
.gitignore, a secret scan on commit, a vault — otherwise it will happen again.
Planned rotation
Rotating a key should never be an event — it is maintenance. A key that has never been rotated is a key nobody knows how to rotate, and that skill always gets discovered at the worst moment: during a leak.
The move is simple because two keys can coexist during the switch: create the new one, deploy it, check that traffic flows, revoke the old one. No interruption. Do it once without urgency, write down the procedure — which secret, in which manager, deployed how — and put a date in the calendar. Twice a year is enough; what matters is not the frequency but that the muscle exists.
Rotation also forces a useful discovery: the real list of places the key lives. If the switch breaks a service nobody remembered, you have just learned something that would have cost far more during an incident.
Keys in a team
With two developers, the key gets passed from hand to hand. With ten, it ends up in a Slack channel, a wiki, a "temporary" file — and each of those places is a leak in the making.
Three rules hold a team together:
- One source of truth: the secrets manager. A key circulating anywhere else is considered compromised, on principle.
- CI gets its own key. Continuous-integration tests run on the sandbox, with a dedicated key that rotation can sacrifice without touching production.
- A member leaving triggers a rotation. Not out of distrust — because a returned workstation, a personal laptop, an individual password manager are all places you no longer control.
And one habit that costs nothing: production keys are never displayed on screen in full. The portal truncates them after creation; your internal tools should do the same.
The right reflex at the start
Before your very first call, add .env and .env.local to your .gitignore, and check that neither is already tracked by git. It is thirty seconds at the start of a project, and it avoids the one category of security incident that is both mundane and expensive.
The portal shows a key exactly once, at creation — in a modal that will not close until you have copied it — and never sends it by email or displays it again, including to you. That constraint is deliberate: a key you can re-read is a key you will eventually re-read somewhere you do not control.
Written by ChariPay team.