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

# Authentication

> API keys, rate limits, and the sandbox.

## API keys

Every request must include your API key in the `X-API-Key` header:

```bash theme={null}
curl https://api.halal.sh/v1/instruments/AAPL/compliance \
  -H "X-API-Key: hsh_sandbox_your_key"
```

Keys are prefixed by environment:

* `hsh_sandbox_` — sandbox keys (free, curated universe)
* `hsh_live_` — live keys (the [Plus plan](https://halal.sh/plans), full universe)

Create and revoke keys from your [API dashboard](https://halal.sh/account/api).

<Note>
  Live keys come with [halal.sh Plus](https://halal.sh/plans) and are for your
  own use: research, automations, and internal workflows. To build a product
  on halal.sh, see the [developer plans](https://halal.sh/developers).
</Note>

<Warning>
  Treat your API key like a password. Never ship it in client-side code, a
  public repository, or a browser request — always call the API from your
  backend.
</Warning>

## The sandbox

Sandbox keys (`hsh_sandbox_`) return real data with the exact same response
schema as production, scoped to a curated set of instruments:

|            | Symbols                                                 |
| ---------- | ------------------------------------------------------- |
| **Stocks** | AAPL, MSFT, NVDA, GOOGL, JPM, GS, META, TSLA, JNJ, AMZN |
| **ETFs**   | SPY, HLAL                                               |

These cover every compliance state — compliant (AAPL), non-compliant (JPM, GS),
and a range of sectors — so you can build and test against each path. Requesting
any other symbol returns `403 sandbox_restricted`. Filter-based screening
(`/screen` without `symbols`) also requires a Plus plan.

## Rate limits

| Plan           | Requests / day | Requests / minute | Evidence packets / month |
| -------------- | -------------- | ----------------- | ------------------------ |
| Sandbox (free) | 100            | 10                | 10                       |
| Pro            | 2,000          | 120               | Unlimited                |
| Enterprise     | Custom         | Custom            | Unlimited                |

Every response includes your current limit state:

```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 2026-06-04T00:00:00.000Z
```

When you exceed a limit, the API returns `429` with a `Retry-After` header and a
`retry_after` field (seconds):

```json theme={null}
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Daily request limit (100) exceeded. Resets at midnight UTC.",
    "retry_after": 3600
  },
  "meta": { "request_id": "req_abc123" }
}
```

The daily window resets at midnight UTC.

## Error handling

Every error uses the same envelope:

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "No instrument found for symbol 'XYZ'."
  },
  "meta": { "request_id": "req_abc123" }
}
```

| HTTP | `code`                | Meaning                                        |
| ---- | --------------------- | ---------------------------------------------- |
| 400  | `bad_request`         | Invalid parameters                             |
| 401  | `unauthorized`        | Missing or invalid API key                     |
| 403  | `sandbox_restricted`  | Symbol or feature not available on the sandbox |
| 404  | `not_found`           | Instrument or resource not found               |
| 429  | `rate_limit_exceeded` | Too many requests                              |
| 503  | `service_unavailable` | Temporary outage — retry with backoff          |
| 500  | `internal_error`      | Server error — retry with backoff              |

Always log `meta.request_id` — it uniquely identifies the request and speeds up
support.

## Response envelope

Every success response has the same shape:

```json theme={null}
{
  "data": { "…": "…" },
  "meta": {
    "request_id": "req_abc123",
    "as_of": "2026-06-03T12:00:00.000Z",
    "methodology": "aaoifi-ss21@2026.1"
  }
}
```

`meta.methodology` is present on compliance-bearing responses and identifies the
exact methodology version used. See [Methodology versioning](/concepts/methodology-versioning).

## Versioning and stability

The API is versioned in the URL path (`/v1`). Within a version we guarantee:

* no fields are removed or renamed,
* no field types change,
* no URL structure changes.

We may **add** fields, endpoints, optional parameters, and enum values within a
version. Design your client to ignore unknown fields and to treat an
unrecognised `status` as `pending`. Breaking changes ship as a new version
(`/v2`) with a migration guide and a deprecation window for the previous one.

## Support

Stuck, or seeing something that looks wrong? [Contact us](https://halal.sh/contact),
and include the `meta.request_id` of any failing request so we can trace it.
