# 

## Why API key security matters

Your API key authenticates every request to Paradise Gateway. A leaked key lets anyone process transactions, access customer data, and create accounts under your client. Treat API keys with the same care as database passwords.

## Threat model

![image](https://files.modern-mermaid.live/images/1776278002663-mermaid-diagram-1776278002779.png)

## Rule 1: Never hard-code keys

Common mistake
Never embed API keys in source code, configuration files committed to version control, or client-side JavaScript.

### Bad — hard-coded in source

```python
# DO NOT DO THIS
API_KEY = "APIKEY-01KEW32V6YNV11T33XGDR7TGWC"
```

### Good — loaded from environment

```python
import os
API_KEY = os.environ["PARADISE_API_KEY"]
```

## Rule 2: Use environment variables

Store API keys in environment variables. This keeps them out of your codebase and lets you use different keys per environment.

Bash
```bash
export PARADISE_API_KEY="your-api-key-here"
export PARADISE_BASE_URL="https://api.dev.paradisegateway.net"
```

PowerShell
```powershell
$env:PARADISE_API_KEY = "your-api-key-here"
$env:PARADISE_BASE_URL = "https://api.dev.paradisegateway.net"
```

.env file
```text
PARADISE_API_KEY=your-api-key-here
PARADISE_BASE_URL=https://api.dev.paradisegateway.net
```

.env files
If using `.env` files, add `.env` to your `.gitignore` immediately. Never commit `.env` files to version control.

### .gitignore entry

```text
# API keys and secrets
.env
.env.*
*.pem
```

## Rule 3: Use a secrets manager in production

Environment variables are fine for development. In production, use a dedicated secrets manager.

| Provider | Service | Benefit |
|  --- | --- | --- |
| AWS | Secrets Manager | Automatic rotation, IAM-based access, audit logging |
| Azure | Key Vault | RBAC, HSM-backed, versioned secrets |
| GCP | Secret Manager | IAM policies, audit logging, automatic replication |
| HashiCorp | Vault | Platform-agnostic, dynamic secrets, lease management |


### Example: AWS Secrets Manager

Python
```python
import boto3, json

def get_api_key() -> str:
    client = boto3.client("secretsmanager", region_name="us-east-1")
    secret = client.get_secret_value(SecretId="paradise-gateway/api-key")
    return json.loads(secret["SecretString"])["api_key"]
```

JavaScript
```javascript
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");

async function getApiKey() {
  const client = new SecretsManagerClient({ region: "us-east-1" });
  const resp = await client.send(
    new GetSecretValueCommand({ SecretId: "paradise-gateway/api-key" })
  );
  return JSON.parse(resp.SecretString).api_key;
}
```

Go
```go
package main

import (
	"context"
	"encoding/json"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
)

func getAPIKey() (string, error) {
	cfg, _ := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-east-1"))
	client := secretsmanager.NewFromConfig(cfg)
	out, err := client.GetSecretValue(context.TODO(), &secretsmanager.GetSecretValueInput{
		SecretId: aws.String("paradise-gateway/api-key"),
	})
	if err != nil {
		return "", err
	}
	var secret map[string]string
	json.Unmarshal([]byte(*out.SecretString), &secret)
	return secret["api_key"], nil
}
```

## Rule 4: Rotate keys regularly

Generate new API keys periodically and when you suspect exposure.

### Rotation steps

![image](https://files.modern-mermaid.live/images/1776278044694-mermaid-diagram-1776278044885.png)

1. **Generate a new key** using `POST /v1/auth/keys` with Basic Authentication.
2. **Update your secrets store** with the new key.
3. **Deploy** so your application picks up the new key.
4. **Verify** by making a test API call.
5. **Monitor** for any failures from the old key (indicates something still using it).


Bash
```bash
curl -s -X POST \
  https://api.dev.paradisegateway.net/v1/auth/keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic $(echo -n 'user@example.com:password' | base64)" \
  | jq -r '.key'
```

PowerShell
```powershell
$cred = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("user@example.com:password"))
$resp = Invoke-RestMethod -Method POST `
  -Uri "https://api.dev.paradisegateway.net/v1/auth/keys" `
  -Headers @{ "Content-Type" = "application/json"; "Authorization" = "Basic $cred" }
$resp.key
```

## Rule 5: Limit key exposure

| Practice | Details |
|  --- | --- |
| **Server-side only** | Never send your API key to a browser or mobile app |
| **Least privilege** | Use separate keys for sandbox and production |
| **One key per service** | If multiple services call the API, each should have its own key |
| **Network restrictions** | If possible, allow API calls only from known IP ranges |
| **Audit access** | Monitor who has access to your secrets manager |


## Rule 6: Detect and respond to leaks

### Prevention

* Add `.env` and secrets files to `.gitignore`
* Use git hooks (e.g., `pre-commit`) to scan for secrets before committing
* Use tools like `gitleaks`, `trufflehog`, or GitHub's secret scanning


### If a key is compromised

1. **Rotate immediately** — generate a new key via `POST /v1/auth/keys`.
2. **Deploy the new key** to all services.
3. **Audit recent activity** — check transaction logs for unauthorized transactions.
4. **Review access** — determine how the key was exposed and close the gap.
5. **Report** — if unauthorized transactions occurred, contact Paradise Gateway support with the `correlation_id` values.


Immediate action required
If you believe your production API key has been compromised, rotate it immediately and audit all transactions from the suspected exposure window.

## Quick reference

| Do | Don't |
|  --- | --- |
| Store keys in environment variables or secrets manager | Hard-code keys in source files |
| Add `.env` to `.gitignore` | Commit secrets to version control |
| Use different keys for sandbox and production | Share a single key across environments |
| Rotate keys on a schedule | Use the same key indefinitely |
| Keep keys server-side only | Expose keys in client-side code |
| Log API calls (redact the key) | Log full API key values |


## Further reading

* [Obtain API credentials](/docs/how-tos/setup/obtain-credentials)
* [Integration best practices](/docs/get-started/integration-best-practices)
* [Data protection](/docs/concepts/security-compliance/data-protection)