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

# Authentication

> API key setup and rate limits for the Macro by Mark API.

# Authentication

The Macro by Mark API uses **API key authentication**. Every request must
include your key in the `X-API-Key` HTTP header.

## Getting your API key

1. Sign in to your [Macro by Mark dashboard](https://macrobymark.com/dashboard).
2. Navigate to **Settings → API Keys**.
3. Click **Create new key**, give it a descriptive name, and copy the value.

<Warning>
  API keys are shown **only once** at creation time. Store yours securely in a
  secrets manager or environment variable — never hard-code it in source code.
</Warning>

## Using your API key

Pass the key in the `X-API-Key` request header on every API call:

```bash theme={null}
curl -G https://api.macrobymark.com/v1/indicators/search \
  --data-urlencode "q=unemployment" \
  -H "X-API-Key: YOUR_API_KEY"
```

### SDK examples

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {"X-API-Key": "YOUR_API_KEY"}
  params  = {"q": "unemployment"}

  resp = requests.get(
      "https://api.macrobymark.com/v1/indicators/search",
      headers=headers,
      params=params,
  )
  resp.raise_for_status()
  print(resp.json())
  ```

  ```javascript JavaScript theme={null}
  const resp = await fetch(
    "https://api.macrobymark.com/v1/indicators/search?q=unemployment",
    { headers: { "X-API-Key": "YOUR_API_KEY" } }
  );
  const data = await resp.json();
  console.log(data);
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.macrobymark.com/v1/indicators/search?q=unemployment",
    {
      headers: { "X-API-Key": process.env.MACRO_API_KEY ?? "" },
    }
  );
  const data: unknown = await response.json();
  ```
</CodeGroup>

## Rate limits

Rate limits are enforced per API key on a rolling 60-second window.

| Plan           | Requests / minute | Requests / day |
| -------------- | ----------------- | -------------- |
| **Free**       | 20                | 500            |
| **Starter**    | 120               | 10,000         |
| **Pro**        | 600               | 100,000        |
| **Enterprise** | Custom            | Custom         |

### Rate limit headers

Every response includes the following headers so you can track consumption:

| Header                  | Description                                    |
| ----------------------- | ---------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the current window |
| `X-RateLimit-Remaining` | Requests remaining in the current window       |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets          |

### Handling 429 errors

When you exceed the rate limit the API returns **HTTP 429** with a
`Retry-After` header indicating how many seconds to wait:

```json theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 14
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1715644814

{
  "error": "rate_limit_exceeded",
  "message": "You have exceeded your request quota. Retry after 14 seconds."
}
```

Implement **exponential back-off** in your client to avoid hammering the API
after a 429:

```python theme={null}
import time, requests

def get_with_retry(url, headers, params, max_retries=5):
    delay = 1
    for attempt in range(max_retries):
        resp = requests.get(url, headers=headers, params=params)
        if resp.status_code == 429:
            retry_after = int(resp.headers.get("Retry-After", delay))
            time.sleep(retry_after)
            delay *= 2
            continue
        resp.raise_for_status()
        return resp.json()
    raise RuntimeError("Max retries exceeded")
```

## Key rotation and revocation

* Rotate keys from **Settings → API Keys** in the dashboard.
* Revoked keys are invalidated immediately.
* You may have up to **5 active keys** per account; Enterprise accounts can
  request higher limits.

## Security best practices

<AccordionGroup>
  <Accordion title="Store keys in environment variables">
    Load your key from `os.environ` (Python), `process.env` (Node.js), or
    equivalent — never embed it directly in source code.
  </Accordion>

  <Accordion title="Use per-project keys">
    Create one key per project or environment (dev/staging/prod) so you can
    revoke a single key without affecting other services.
  </Accordion>

  <Accordion title="Restrict key usage">
    Enterprise plan keys support IP allow-listing and scoped permissions.
    Contact support to enable these features.
  </Accordion>
</AccordionGroup>
