Trade-only API keys: the one setting that limits the damage
When I set up the connection between my bot and the exchange, one setting mattered more than any strategy tweak I made afterward: the API key permissions. On Bitvavo, like most exchanges, you can generate a key that is allowed to place trades but has no permission to withdraw funds. I turned withdrawal permission off before the bot ever ran, and I have never turned it back on.
This is not a clever trick. It is a basic setting sitting in plain view on the key management page. Most people skip it because they are focused on getting the bot to work, not on what happens if something goes wrong later. I think that order of priorities is backwards.
What a trade-only key actually protects against
If the key that my bot uses ever leaks, through a misconfigured server, a copied script, or a mistake on my part, whoever gets hold of it can log in and place trades on my behalf. That is bad. But they cannot move my euros or my bitcoin to a wallet of their own, because the key itself has no withdrawal rights. The worst they can do is trade badly with my money while it stays inside my account. Annoying, possibly costly, but not the same as having my funds disappear entirely.
That distinction is the whole point of a trade-only key. It narrows the blast radius of a leak from total loss to a bounded, recoverable mess. I can revoke the key, generate a new one, and assess the damage. Nobody has walked away with my balance.
What it does not protect against
I want to be honest about the limits here, because it would be easy to read this and think a trade-only key makes the bot safe. It does not. A trade-only key protects against theft through a leaked credential. It does nothing to protect against a bad strategy, a market that moves against a position, or a bug in the code that buys or sells at the wrong moment. My bot can still lose money the ordinary way, by trading, with permission, exactly as it was told to. No permission setting fixes that. The setting is damage control for one specific failure mode, not a safety net for the whole system.
Where the key lives, and rotating it
The other half of this is just as unglamorous: the key should never sit inside your code. If you paste an API key directly into a script and that script ends up in a public repository, or even just gets shared with someone by accident, the key is exposed regardless of what permissions it has. I keep mine in environment secrets, the kind of storage Replit and most hosting platforms provide, separate from the code itself. The bot reads the key at runtime; it is never written into a file that gets copied around.
I also rotate the key periodically, meaning I generate a fresh one and retire the old one, rather than letting the same credential run indefinitely. Rotation limits how long a leaked key would even remain useful if it did get out, and it forces me to check, every time, that the new key is set up with the same restricted permissions as the last one. That habit is a bit tedious. It is also cheap insurance against carelessness.
The Edge Perspective
I did not build this bot to prove I understood exchange security. I built it so the trading itself would stop taking up my evenings, running on Bitvavo around the clock so I do not have to watch it. But taking that time back only makes sense if I am not trading a real risk of theft for a small risk of a bad trade. The trade-only key is the setting that keeps those two risks separate, so the automation gives me time back instead of quietly creating a new problem I have not noticed yet.
None of this removes the ordinary risk of trading. It only closes one specific door. The rest, the strategy, the code, the market itself, still needs the same caution it would need with any key that has full permissions.
Disclaimer: this article shares my personal experience and is not financial advice. Crypto and traded products are risky — prices can fall hard, and a system that worked in the past is no guarantee for the future. Only trade with money you can afford to lose.