---
title: "Authentication & API Keys"
source: https://sumgenius.ai/docs/api-authentication
generated: 2026-09-14
---

# Authentication & API Keys

One kind of key opens everything: the [REST API](https://sumgenius.ai/docs/rest-api), the [Send API](https://sumgenius.ai/docs/send-api), and webhook management. This page covers the key format, the headers, and managing keys in the portal.

Webhook & API Add-on · $29/month · Requires Creator+ plan

### API keys

Keys are created in the portal under **Integrations → Webhook & Send API**. A key is a 53-character string: the prefix `sgwh_` followed by 48 hex characters.

- named keysup to 10 active Create a key per system ("Production backend", "Zapier", "Partner CRM") so each can be rotated or revoked without touching the others.
- preview The portal lists each key by name with its last 8 characters, plus when it was created, last rotated, and last used.
- storage We store keys hashed for authentication; the account owner can re-reveal a key's full value from the portal.

> **Warning**
>
> A key is a server-side credential. Never ship it in a browser, mobile app, or public repo. The REST and Send APIs have no CORS on purpose: they are not callable from front-end code.

**Key format**

```
sgwh_................................................
└─┬─┘ └──────────────────── 48 hex ────────────────────┘
prefix
```

**Portal key list**

```
Production backend   sgwh_…c1d94ab2   last used 2m ago
Zapier               sgwh_…88f0e3aa   last used 3d ago
Partner CRM          sgwh_…41b7cc09   never used
```

### Sending the key

Send the key on every request as any one of three headers. All three are equivalent on every endpoint of both APIs; `X-SumGenius-Api-Key` is preferred.

- X-SumGenius-Api-Keypreferred
- X-API-Key
- Authorization: Bearer

Auth errors

- 401 unauthorized No key sent.
- 401 invalid_api_key Key not recognized, revoked, or rotated away.
- 403 addon_inactive Key is valid but the Webhook & API Add-on is not active on the account.

**The three headers**

```
# preferred
curl https://sumgenius.ai/api/v1/account \
  -H "X-SumGenius-Api-Key: sgwh_your_api_key_here"

# equivalent
curl https://sumgenius.ai/api/v1/account \
  -H "X-API-Key: sgwh_your_api_key_here"

curl https://sumgenius.ai/api/v1/account \
  -H "Authorization: Bearer sgwh_your_api_key_here"
```

**Error 401**

```
{
  "error": {
    "code": "invalid_api_key",
    "message": "API key not recognized."
  }
}
```

### Create, rotate, revoke

- Create Name it after the system that will hold it. The full key is shown on creation; copy it into that system's secret store.
- Rotate Replaces the key's secret in place: same name, same entry, new value. The old value stops working immediately, so update the consuming system in the same sitting. If a key may be exposed, rotate it first and investigate second.
- Revoke Kills the key immediately and permanently. Revoked keys cannot be restored; create a new one instead.

> **Tip**
>
> Webhook **signing secrets** are separate credentials, one per endpoint, used to verify deliveries we send to you. Keys authenticate you to us; secrets authenticate us to you. Secret rotation has a 24-hour grace window; see [Verifying signatures](https://sumgenius.ai/docs/receiving-webhooks#verify).

**Rotation checklist**

```
1. Portal → Integrations → Webhook & Send API
2. Rotate the key for the affected system
3. Copy the new value into that system's secrets
4. Confirm its next API call returns 200
5. Old value is already dead, nothing to clean up
```

### Key scopes

Every key carries a scope chosen when it is created. The scope cannot be changed afterwards: create a new key with the scope you need and revoke the old one. Keys created before September 2026 have full access, which behaves as `admin`.

- read Every `GET` endpoint. Nothing else, on either API. Use it for dashboards, reporting, and any system that should never be able to change or send anything.
- write Everything in `read`, plus creating, updating, sending and deleting business records: contacts, tags, custom fields, conversations, messages. This is the right default for an integration.
- admin Everything in `write`, plus account-level configuration as those endpoints ship: AI settings, channel switches, webhook endpoints and API keys.

A call outside the key's scope returns `403` with code `insufficient_scope`. The response names both the scope the key holds and the scope the endpoint needs. [GET /account](https://sumgenius.ai/docs/rest-api#get-account) reports the calling key's scope, so an integration can check what it holds before attempting a write.

**403 insufficient_scope**

```
{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key has the read scope; this endpoint needs write.",
    "required_scope": "write",
    "key_scope": "read"
  }
}
```

**What each scope reaches**

```
read    GET /api/v1/*
write   read  + POST, PATCH, DELETE on business records
        + POST /api/meta/webhook-send.php
admin   write + account-level configuration
```

### OAuth 2.1, for apps acting on behalf of an owner

API keys are for your own server. When a third party acts for one of our account owners, such as an AI assistant through the [hosted MCP server](https://sumgenius.ai/docs/mcp), it uses OAuth 2.1 instead: the owner signs in to ChatGenius, sees what the app wants, and clicks Allow. The app never sees a password or a key, and the owner can revoke it from *Settings, AI assistants*.

What we support

- GrantAuthorization code with PKCE (S256 only). Public clients only, no client secrets.
- Client identityDynamic client registration (RFC 7591) at the registration endpoint, or a client ID metadata document: send an https URL as `client_id` and we fetch and cache the document.
- Redirect URIsExact match. https anywhere, http only on localhost.
- Scopes`read` or `write`. The owner can downgrade a write request to read on the consent page. `admin` is never granted over OAuth.
- TokensAccess tokens (`sgat_`) last one hour and go in `Authorization: Bearer` exactly like a key. Refresh tokens (`sgrt_`) last 30 days and rotate on every use; reusing an old one revokes the whole grant.
- CodesSingle use, five minutes, bound to the app, the redirect URI and the PKCE challenge.

**Discovery**

```
GET https://sumgenius.ai/.well-known/oauth-authorization-server
GET https://sumgenius.ai/.well-known/oauth-protected-resource
```

**Endpoints**

```
authorize   https://sumgenius.ai/portal/oauth/authorize.php
token       https://sumgenius.ai/api/oauth/token.php
register    https://sumgenius.ai/api/oauth/register.php
revoke      https://sumgenius.ai/api/oauth/revoke.php
```

**Token exchange**

```
POST /api/oauth/token.php
grant_type=authorization_code
&code=...&code_verifier=...
&client_id=...&redirect_uri=...

{ "access_token": "sgat_...", "refresh_token": "sgrt_...",
  "token_type": "Bearer", "expires_in": 3600, "scope": "write" }
```
