Security Best Practices
Secure your GaiaEx API integration: credential management, IP whitelisting, key rotation intervals, and audit logging for production systems.
Security Best Practices
API key security is your responsibility. A compromised key can execute trades against your deposited balance and read your account data. It cannot move funds off the platform — withdrawals, deposits, and on-chain transfers all require the user's embedded-wallet signature plus a passkey step-up, which are only available in the mobile app. This guide covers battle-tested practices used by institutional trading desks.
NEVER HARDCODE CREDENTIALS
Never paste API keys or secrets directly into source code, scripts, notebooks, or commit them to version control. A single leaked credential in a public GitHub repo can be exploited within minutes by automated scanners.
Credential Storage: Environment Variables (Recommended)
Store credentials as environment variables, not in a file that lives in your project directory. This is the standard approach for local scripts, CI/CD pipelines, Docker containers, and cloud servers.
Step 1: Export the variables
# Set in your shell profile (~/.bashrc, ~/.zshrc), systemd EnvironmentFile, or CI/CD secrets manager — not a project file
export GAIAEX_API_KEY="a1b2c3d4e5f6789012345678abcdef00"
export GAIAEX_API_SECRET="s3cr3t_k3y_n3v3r_sh4r3_th1s"
export GAIAEX_ADDRESS="0xA6E3c04eF78427b5B53F43CDBA881d7E15B0bccD"Step 2: Read them in your code
Python:
import os
API_KEY = os.environ["GAIAEX_API_KEY"]
API_SECRET = os.environ["GAIAEX_API_SECRET"]
ADDRESS = os.environ["GAIAEX_ADDRESS"]JavaScript / Node.js:
const API_KEY = process.env.GAIAEX_API_KEY;
const API_SECRET = process.env.GAIAEX_API_SECRET;
const ADDRESS = process.env.GAIAEX_ADDRESS;Rust:
let api_key = std::env::var("GAIAEX_API_KEY")?;
let api_secret = std::env::var("GAIAEX_API_SECRET")?;
let address = std::env::var("GAIAEX_ADDRESS")?;DOCKER / CI
Pass credentials via docker run -e GAIAEX_API_KEY=... , a Docker secret, or your CI provider's encrypted secrets store — never bake them into an image layer or repo file.
Production: Managed Secrets Stores
For production trading bots and servers, go one step further than environment variables: pull credentials at runtime from a managed secrets service rather than setting them as plain shell exports. This adds encryption at rest, access auditing, and rotation without redeploying code.
| Platform | Service |
|---|---|
| AWS | Secrets Manager / Parameter Store (SecureString) |
| Azure | Key Vault |
| GCP | Secret Manager |
| Self-hosted | HashiCorp Vault |
Typical pattern: your process boots, calls the secrets service with an IAM role (no static credential needed to fetch the secret itself), receives the API key/secret in memory, and never writes it to disk.
Storage Options Compared
| Method | Best For | Risk Level |
|---|---|---|
| AWS Secrets Manager / Azure Key Vault / GCP Secret Manager | Production servers, trading bots | Lowest |
| Environment variables | Local dev, CI/CD, Docker, cloud servers | Low |
Local file (e.g. config.json, gitignored) | Quick local prototyping only | Medium — a file on disk can be read by any process/backup/misconfigured permission; avoid for anything beyond throwaway local testing |
| Hardcoded in source | Never | Critical — never do this |
IP Whitelisting
Lock your API key to specific IP addresses. Even if the key leaks, it cannot be used from unauthorized locations.
{
"ip_whitelist": ["203.0.113.50", "198.51.100.0/24"]
}Configure IP whitelisting when creating an API key via the GaiaEx mobile app. (POST /api-keys requires passkey step-up and is effectively app-only.)
| Scenario | Recommendation |
|---|---|
| VPS/dedicated server | Whitelist the server's static IP |
| Home connection | Use a VPN with a static IP, then whitelist that |
| CI/CD pipeline | Whitelist your CI provider's IP range |
| Development (dynamic IP) | Use a separate dev key with read-only permissions |
TIP
If your IP changes frequently, create two API keys: one locked-down key for production (with IP whitelist + trade permission), and one read-only key for development (no IP restriction, read-only permission).
Permission Scoping (Principle of Least Privilege)
GaiaEx API keys support granular permissions. Only grant the minimum permissions needed.
| Permission | Allows | Use Case |
|---|---|---|
read | View balances, positions, orders, market data | Monitoring dashboards, analytics bots |
trade | Place, cancel, modify orders; close positions | Trading bots, strategy execution |
Recommendation:
- Monitoring scripts →
["read"]only - Trading bots →
["read", "trade"] - Never create "all permissions" keys unless absolutely necessary
Key Rotation
Rotate API keys regularly — especially after team member departures, suspected leaks, or security incidents.
Rotation Procedure
- Create a new key via the GaiaEx app or
POST /api-keys(note:POST /api-keysrequires a passkey step-up challenge and is effectively app-only — bots cannot self-issue keys) - Update your credential store — environment variables or secrets manager — with the new key
- Verify the new key works (call
GET /timeorGET /health) - Revoke the old key via
DELETE /api-keys/{api_key}
Recommended rotation schedule:
| Scenario | Frequency |
|---|---|
| Production trading bot | Every 30–90 days |
| After team member leaves | Immediately |
| After suspected leak | Immediately |
| Development / testing key | Every 90 days |
Audit & Monitoring
Monitor your API key activity for unauthorized access.
- Check the audit log via
GET /api-keys/{api_key}/audit— shows lifecycle events (created, updated, revoked) for this key. Per-request call logs are not available. - Monitor order history — unexpected orders may indicate compromised keys
- Set up alerts — use User Data Stream WebSocket to get real-time notifications of trades and balance changes
What to Watch For
| Signal | Action |
|---|---|
| API calls from unknown IPs | Rotate key immediately, enable IP whitelist |
| Orders you didn't place | Revoke key, cancel all orders, secure wallet |
| Authentication failures spike | Someone may be brute-forcing — enable IP whitelist |
| Rate limit hits you didn't cause | Your key may be in use elsewhere — rotate |
Security Checklist
| # | Item | Status |
|---|---|---|
| 1 | Credentials in environment variables or a secrets manager — never hardcoded, never in a project file | ☐ |
| 2 | If a local credential file is used for prototyping, it is in .gitignore and never committed | ☐ |
| 3 | IP whitelist enabled for production keys | ☐ |
| 4 | Minimum permissions granted (read-only where possible) | ☐ |
| 5 | API keys rotated every 30–90 days | ☐ |
| 6 | Separate keys for production and development | ☐ |
| 7 | Audit logs reviewed weekly | ☐ |
| 8 | Team onboarding doc explains where to get credentials (secrets manager / CI vault) — no shared plaintext files | ☐ |
| 9 | WebSocket user stream connected for real-time trade monitoring | ☐ |