Guides

Security & Data

What's encrypted, what stays on your instance, and exactly what Ionide-operated services ever see.

Ionide doesn't custody funds and isn't an exchange. Your assets stay on the exchange account you connect, and Ionide only ever gets trading-only API access to it. This page covers how your exchange credentials are stored, and precisely what data does or doesn't leave your own self-hosted instance.

How your exchange API keys are stored

  • Keys are encrypted with AES-256-GCM before being written to your instance's local database (a Docker volume, /app/data), using a key you generate yourself: the installer runs openssl rand -hex 32 for you and writes it to your local .env as SECRETS_ENCRYPTION_KEY.
  • The encryption key is independent of your Discord bot token, so rotating one never invalidates the other.
  • /secrets action:status shows which exchanges have credentials configured without ever decrypting them. Stored values are never echoed back in Discord, not even to the bot owner.
  • Decryption happens only in-memory, at the moment the bot places or checks on a trade for you. It's never part of any request to an Ionide-operated service.

What never leaves your instance

Your raw API key, secret, and (for Bitget) passphrase are never transmitted anywhere once you've entered them via /secrets action:set: not to product-api, not to alpha-engine, not in logs. If you lose your SECRETS_ENCRYPTION_KEY, those stored credentials can't be decrypted by anyone, including us. You'd need to run /secrets action:set again with a new key.

What does leave your instance

Your license key and a generated instance ID accompany every request below, used to validate entitlement (/v1/license-validations) and associate your instance with your license.

  • Command-center rendering: aggregate trading metrics (APR, PnL, max drawdown, and per-symbol funding-profit series). The same numbers /pnl and /summary show you in Discord are sent so the summary/chart images product-api renders for your command center reflect your actual results.
  • Heartbeat (every 5 minutes, while the bot is running): your currently-open positions (symbol, side, notional size, last-updated time), per-exchange API latency stats, JVM memory/uptime/thread count, and cumulative trade entry/exit counts (successful, failed, simulated). This is what lets us confirm an instance is alive and see current arbitrage state without you having to report it.
  • Exception reports (sent immediately, off the bot's main thread, whenever it hits an unhandled error): the exception's message, its full stack trace, and a short label of where it occurred, so issues can get caught and fixed without you having to report them yourself.

That's the complete list. No exchange credentials, no wallet addresses, and no per-trade order details are included in any of it.

Permission scoping

Ionide only ever requests trading permissions on your exchange API key, never withdrawal access. See Adding Exchange API Keys for exact steps per exchange, and run /secrets action:test after setting a key: it checks the key works and, where the exchange's API exposes it, confirms withdrawal permission is actually off. Revoke a key from your exchange's own dashboard at any time: the bot loses trading access immediately but never had a way to move funds out in the first place.

Your own infrastructure

Ionide runs as a container on infrastructure you control. Docker host security (OS updates, SSH access, who can reach your Docker daemon) is your responsibility, the same as any other self-hosted service. See Self-Hosting Ionide for what the installer does and where the encryption key and database live so you can back them up.

Questions?

Reach out on Discord or [email protected].