---
title: Authentication
description: Every API request must include a valid secret key in the Authorization header.
source: https://www.edgaze.ai/docs/api/authentication
section: api
---
# Authentication

> Every API request must include a valid secret key in the Authorization header.

Every API request must include a valid secret key in the Authorization header. Keys are scoped, revocable, and optionally spend-capped: create and manage them in the [Developer console](/developer/keys).

## Key format

```
Authorization: Bearer edgaze_sk_live_…
```

Keys follow the pattern `edgaze_sk_{live|test}_…`. The plaintext is shown once at creation in the Developer console. Only a SHA-256 hash is stored server-side: if you lose the key, revoke it and create a new one.

Never commit keys to source control. Use environment variables or a secrets manager, and rotate keys if exposure is suspected.

## Scopes

Each key is issued with one or more scopes. The API rejects requests that lack the required scope.

| Scope         | Access                       |
| ------------- | ---------------------------- |
| `run:execute` | POST /runs                   |
| `run:read`    | GET /workflows, GET /runs/\* |

Default keys include both scopes. Read endpoints accept either scope, so a read-only key can list workflows and poll runs without execute permission.

## Security behavior

The API is designed to avoid leaking tenant or resource existence.

- Invalid, revoked, or expired keys always return **401** with the same message: no enumeration of which condition applied.
- Cross-tenant resource access returns **404** for runs, not 403. You cannot probe whether a run id exists in another account.
- Workflow entitlement denial returns **403 forbidden** with a uniform message when you are authenticated but not allowed to run a listing.
- Scope violations return **403 insufficient_scope** before any handler logic runs.
