> ## Documentation Index
> Fetch the complete documentation index at: https://docs.safefetch.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> How SafeFetch handles your data and what to consider when sending sensitive action bodies.

## Data storage

SafeFetch stores the following data for each action:

| Field           | Stored | Notes                                             |
| --------------- | ------ | ------------------------------------------------- |
| `body`          | ✅      | The request body you send when creating an action |
| `headers`       | ✅      | Custom headers you attach to the action           |
| `response_body` | ✅      | The response from your target API                 |
| `response_code` | ✅      | HTTP status code from your target API             |
| `url`           | ✅      | The target URL                                    |
| `callback`      | ✅      | Where results are forwarded (if set)              |

All data is stored durably with encryption at rest enabled by default.

## Best practices

### Don't put raw secrets in action bodies

Instead of:

```json theme={null}
{
  "url": "https://myapp.com/process",
  "body": {
    "stripe_key": "sk_live_abc123",
    "database_url": "postgres://user:pass@host/db"
  }
}
```

Use references that your endpoint resolves:

```json theme={null}
{
  "url": "https://myapp.com/process",
  "body": {
    "stripe_key_ref": "vault://production/stripe-key",
    "action_type": "charge-customer"
  }
}
```

Your endpoint handler looks up the actual secret from your vault/env at execution time.

### Don't put auth tokens in custom headers unless necessary

If your endpoint requires authentication, prefer a pre-shared token that your endpoint validates, not a token with broad permissions:

```json theme={null}
{
  "url": "https://myapp.com/api/process",
  "headers": {
    "X-Delivery-Secret": "whsec_safefetch_only_token"
  }
}
```

Use a dedicated, scoped token for SafeFetch deliveries rather than your main API keys.

### Use HMAC verification on your endpoints

Every SafeFetch delivery includes an `X-SafeFetch-Signature` header. Always verify it:

```typescript theme={null}
import { createHmac, timingSafeEqual } from 'crypto';

function verify(body: string, signature: string, apiKey: string): boolean {
  const expected = `sha256=${createHmac('sha256', apiKey).update(body).digest('hex')}`;
  return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
```

This ensures the request actually came from SafeFetch, not an attacker hitting your API.

## Transport security

* All connections to the SafeFetch API are over **HTTPS/TLS**
* Deliveries are always made over **HTTPS** (HTTP targets are rejected)
* Database connections use **TLS with certificate verification**

## Encryption at rest

All data is encrypted at rest.

## Access control

* Each account has its own API key
* All API queries are scoped by `account_id` — you can only access your own actions
* API keys are stored as hashed values (not plaintext) in the database

## Coming soon

<Note>
  These features are planned for future releases.
</Note>

### Redacted responses

```json theme={null}
{
  "url": "https://myapp.com/sensitive-endpoint",
  "body": { "user_id": 42 },
  "redact_response": true
}
```

When `redact_response` is enabled, SafeFetch stores the status code and duration but **discards the response body**. Useful when your endpoint returns sensitive data (PII, financial records, health data) that shouldn't be retained.

### Retention TTL

```json theme={null}
{
  "url": "https://myapp.com/process",
  "body": { "file": "data.csv" },
  "retention": "7d"
}
```

Automatically purge all action data (body, headers, response) after the specified period. Data is permanently deleted — not soft-deleted. Supported values: `1d`, `7d`, `30d`, `90d`.

### Per-account body encryption

Encrypt `body`, `headers`, and `response_body` with a per-account key. Even if the database is compromised, action data is unreadable without the account's encryption key. Available on Team and Enterprise plans.
