> For the complete documentation index, see [llms.txt](/llms.txt).
> A full single-fetch corpus is available at [llms-full.txt](/llms-full.txt).
---
title: "Authentication"
description: "Authenticate requests to the AGNT5 API with a personal API key or a bearer token, and understand the error envelope and rate limits every endpoint shares."
last_verified: 2026-07-27
---


**APIs**: gateway `https://gw.agnt5.com` (run components, runs, run events, workflow resume) takes a service key in `X-API-KEY`, plus `X-DEPLOYMENT-ID` unless the key was created for one environment; control plane `https://api.agnt5.com/api/v1` takes the credentials below
**Auth**: `X-API-KEY: <personal_api_key>` (required) or `Authorization: Bearer <jwt_or_opaque_token>` — exactly one is required on every request
**Error envelope**: most 4xx/5xx responses return `{"error": string, "message": string, "code": int, "hint"?: string}`; a missing or invalid credential returns a plain-text `401` instead
**Rate limits**: per-credential, tier-based (30-3,000 requests/minute); a `429` response includes a `Retry-After` header


AGNT5 has two HTTP APIs, and each takes its own credential:

| API | Base URL | Use it to | Credential |
|---|---|---|---|
| **Gateway** | `https://gw.agnt5.com` | Run components, read runs and their output, follow run events, resume workflows | A [service key](/docs/build/local-development.md#create-a-service-key) in `X-API-KEY` |
| **Control plane** | `https://api.agnt5.com/api/v1` | Manage projects, environments, secrets, deployments, datasets, experiments, and other resources | A personal API key in `X-API-KEY`, or a bearer token |

The gateway endpoints are listed under [Runs & Traces](/docs/api-reference/runs-and-traces.md): [run a component](/docs/api-reference/runs-and-traces/run-a-component.md), [list runs](/docs/api-reference/runs-and-traces/list-gateway-runs.md), [run events](/docs/api-reference/runs-and-traces/run-events.md), and [resume a workflow](/docs/api-reference/runs-and-traces/resume-a-workflow.md).

## Gateway service keys

Create a service key with the CLI. Keys get the `run` scope by default; add `workflow` to resume paused workflows:

```bash
agnt5 service-keys create --name "production-runner" --project <project-id> --scopes run,workflow
```

Pass `--environment <environment-id>` to create the key for one environment. Requests with that key run against the environment's live deployment. A key without an environment needs `X-DEPLOYMENT-ID: <deployment-id>` on each request.

## Control plane credentials

Every request to the control plane must carry one of two credentials: a personal **API key** or a **bearer token**. The rest of this page covers both, the shape of error responses, and the rate limits applied per credential.

### Choose a credential

* **API key** (`X-API-KEY` header): a personal key issued in Studio.
* **Bearer token** (`Authorization: Bearer <token>` header): a session JWT issued when you sign in to Studio, or an OAuth 2.1 opaque token for MCP-based integrations.

```bash
curl https://api.agnt5.com/api/v1/projects \
  -H "X-API-KEY: <your_api_key>"
```

```bash
curl https://api.agnt5.com/api/v1/projects \
  -H "Authorization: Bearer <your_jwt>"
```

Send exactly one of the two headers. If neither is present, or the credential is invalid, the API responds `401 Unauthorized` with a **plain-text body** (for example `Invalid or missing authorization header`) — this is the one place in the API that doesn't use the JSON error envelope described below, because the failure happens before request routing.

## Error envelope

Once a request is authenticated, every error response — validation failures, not-found errors, database errors — uses the same JSON shape:

```json {{ title: 'Error response' }}
{
  "error": "Invalid query parameters",
  "message": "page_size must be between 1 and 100",
  "code": 400,
  "hint": "Pass page_size between 1 and 100"
}
```

`hint` is optional and only present when the API can suggest a concrete fix.

> **Note:** A few observability endpoints ([Runs & Traces](/docs/api-reference/runs-and-traces.md)) predate this shared envelope and return a narrower `{"error": string, "message": string}` shape with no `code` field. Each affected endpoint calls this out individually.

## Success envelope

Successful responses wrap their payload in a consistent envelope:

```json {{ title: 'List response' }}
{
  "success": true,
  "message": "Projects retrieved successfully",
  "data": [ /* ... */ ],
  "metadata": {
    "count": 42,
    "page": 1,
    "hasNext": true,
    "hasPrev": false,
    "unfilteredCount": 42,
    "hasAny": true
  }
}
```

Single-resource `GET` responses (`GET /api/v1/projects/:id`, for example) use the same `{success, message, data}` shape without `metadata`.

## Rate limits

Requests are rate-limited per credential and per plan tier, with separate per-minute and per-day budgets:

| Tier | Requests / minute | Requests / day |
|---|---|---|
| Free | 30 | 1,000 |
| Pro | 300 | 50,000 |
| Enterprise | 3,000 | Unlimited |

An API key is bucketed by a hash of the key value; a bearer token is bucketed by the signed-in user. Exceeding your limit returns:

```json {{ title: '429 Too Many Requests' }}
{
  "error": "rate_limited",
  "message": "rate limit exceeded for minute window",
  "window": "minute",
  "limit": 30
}
```

The response also carries a `Retry-After` header (seconds) telling you when to retry. If the rate limiter's backing store is temporarily unavailable, requests are allowed through rather than blocked — a store outage never blocks your traffic.

## Next steps

* [Projects](/docs/api-reference/projects.md): list and inspect the projects your credential can access
* [Deployments](/docs/api-reference/deployments.md): the resource most endpoints scope their queries to
* [Secrets](/docs/api-reference/secrets.md): store the credentials your deployed workflows need
* [CLI authentication](/docs/cli/auth.md): how **`agnt5 login`** obtains and stores a credential locally
