# Authenticating AI Agents with GetScaled

GetScaled exposes a public REST API at `https://api.getscaled.com` and a Model
Context Protocol (MCP) server at `https://mcp.getscaled.com`. Agents authenticate
with either a scoped API key (`gsk_` prefix, sent as a Bearer token) or an OAuth
2.1 access token issued by our authorization server (`agent_auth`).

## Discover

Fetch the protected-resource metadata to learn where and how to authenticate:

```
GET https://api.getscaled.com/.well-known/oauth-protected-resource
```

An unauthenticated API request returns `401` with a discovery hint header:

```
WWW-Authenticate: Bearer resource_metadata="https://api.getscaled.com/.well-known/oauth-protected-resource"
```

The authorization-server metadata (RFC 8414, advertising
`code_challenge_methods_supported: ["S256"]`) is at:

```
GET https://api.getscaled.com/.well-known/oauth-authorization-server
```

## Pick a method

| Method | identity_type | Best for |
|--------|---------------|----------|
| API key (`gsk_`) | `anonymous` | Server-to-server agents, MCP clients, CLI |
| OAuth 2.1 + PKCE (S256) | `identity_assertion` | User-delegated access, ChatGPT/Claude connectors |

## Register

Programmatic agents request a credential at the `register_uri`:

```
POST https://api.getscaled.com/agent/auth/register
Content-Type: application/json

{ "client_name": "my-agent", "identity_type": "anonymous", "scopes": ["campaigns:read","contacts:read"] }
```

Humans self-serve a key in the portal: **portal.getscaled.com → Admin → API Keys → Issue Key**.

## Claim

Exchange a registration handle for an active credential at the `claim_uri`:

```
POST https://api.getscaled.com/agent/auth/claim
Content-Type: application/json

{ "registration_id": "<from register>", "identity_assertion": "<optional id-jag / verified_email>" }
```

For OAuth, complete the authorization-code + PKCE flow against the authorization
server discovered above. `urn:ietf:params:oauth:token-type:id-jag` assertions are
accepted inside `identity_assertion`.

## Use the credential

Send the credential as a Bearer token on every request:

```
GET https://api.getscaled.com/api/v1/campaigns
Authorization: Bearer gsk_your_key_here
```

The same key authenticates the MCP server at `https://mcp.getscaled.com` (Streamable HTTP).

## Errors

| Status | Meaning | Recovery |
|--------|---------|----------|
| `401 UNAUTHORIZED` | Missing/invalid credential | Re-read `WWW-Authenticate`, re-register, retry |
| `403 FORBIDDEN` | Key lacks the required scope | Request a key with the scope named in the body |
| `429` | Rate limited | Back off and honor `Retry-After` |

## Revocation

Revoke a credential at the `revocation_uri`:

```
POST https://api.getscaled.com/agent/auth/revoke
Content-Type: application/json

{ "credential": "gsk_your_key_here" }
```

Keys can also be revoked in the portal under **Admin → API Keys**.

---
Spec reference: https://workos.com/auth-md · Scopes: `campaigns:read`, `campaigns:write`, `campaigns:launch`, `contacts:read`, `contacts:write`, `journeys:read`, `journeys:write`, `analytics:read`, `lists:write`, `templates:write`, `compliance:read`, `admin:*`
