# Authentication

Hooksbase has three public auth models, and each one maps to a different job. Use a session for dashboard product flows, a project API key for the Public API, and a webhook ingest or signing secret only for the one webhook that issued it. Secrets are not interchangeable — using the wrong one returns 401.

> [!NOTE]
> Every raw secret (project API key, ingest secret, signing secret) is returned exactly once on create or rotate. List and get routes only return non-sensitive metadata and version ledgers. Copy new secrets into your secret manager immediately.

## Auth surfaces

- **Dashboard** `session auth`: The [Hooksbase dashboard](https://app.hooksbase.com) uses your browser session. It is a product UI, not part of the Public API, and is not reachable with a project API key.
- **Public API** `project API key`: The Public API uses `Authorization: Bearer swk_...`. Use this for webhook configuration, delivery history, replay, usage, and other automation-friendly routes.
- **Public ingest** `webhook secret`: The public ingest surface uses the webhook's `whsec_...` secret against the webhook-specific ingest URL.

## Project API keys

Project API keys have a `swk_` prefix and come in two roles:

- `admin` can use `/v1/project`, manage project API keys, and access admin-only project routes such as audit logs and operator notification APIs when the project tier allows them.
- `write` can use operational routes such as `/v1/webhooks`, `/v1/deliveries`, `/v1/dlq`, `/v1/usage`, and webhook schedules, but cannot read or mutate `/v1/project` or manage project API keys.

Pick the narrowest role that works for the caller. Prefer `write` for CI, ETL jobs, and agent workloads that only operate on webhooks and deliveries; reserve `admin` for key management and project settings.

**Project API key request**

```bash
curl https://api.hooksbase.com/v1/project \
  -H "Authorization: Bearer swk_..."
```

API key lifecycle rules are strict:

- list and get routes never return the raw secret (only the prefix and metadata)
- create and rotate return the secret exactly once
- a project cannot revoke its last active admin key — create a replacement first, then revoke the older key

## Ingest secrets

Every webhook has its own ingest secret. Use it only when calling that webhook's public ingest URL:

**Public ingest request**

```bash
curl "${INGEST_URL}" \
  -H "Authorization: Bearer whsec_..." \
  -H "content-type: application/json" \
  -d '{"type":"order.created"}'
```

During a secret-overlap window, Hooksbase accepts both the current ingest secret and the overlapping predecessor until the older version reaches its `retiredAt` timestamp.

## Signing secrets

Signing secrets are outbound-only. Hooksbase uses them to sign deliveries sent to your destination. They are not valid for calling any Hooksbase API route.

Outbound requests include:

- `webhook-id`
- `webhook-timestamp`
- `webhook-signature`

The signature payload is:

```text
{deliveryId}.{unixTimestampSeconds}.<raw body bytes>
```

The header format is `v1,<base64 hmac sha256>`. During a signing overlap window Hooksbase can send more than one `v1,...` signature in the same header.

## Related routes

- `GET /v1/project`
- `GET/POST /v1/project/api-keys`
- `POST /v1/project/api-keys/{keyId}/revoke`
- `POST /v1/project/api-keys/{keyId}/rotate`
- `POST /v1/ingest/{publicId}`
- `POST /v1/webhooks/{id}/rotate-ingest-secret`
- `POST /v1/webhooks/{id}/rotate-signing-secret`
- `GET /v1/webhooks/{id}/secret-versions`

## Common mistakes

- Expecting a project API key to unlock dashboard views. The dashboard uses session auth and is not reachable via `swk_` keys.
- Using a write key for an admin-only route such as `/v1/project`.
- Reusing one webhook's ingest secret with another webhook's ingest URL.
- Verifying the signature against a reconstructed string instead of the raw body bytes.
