---
title: "Authorization endpoint (authorization-code + PKCE)"
method: GET
path: "/authorize"
tags: ["Identity Provider"]
---

# Authorization endpoint (authorization-code + PKCE)

`GET /authorize`

## Request

- Base URL: `https://id.deadsimple.email`
- URL: `https://id.deadsimple.email/authorize`
- Auth: none required

Three ways an agent authenticates, checked in this order.
1. **API key**: send `Authorization: Bearer dse_...` plus `inbox_id=` (or `login_hint=<inbox email>`; both may be omitted when the account has exactly one inbox). The code is minted immediately.
2. **Signed assertion**: `assertion=` an ES256 JWS over `{iss: inbox_id, sub: inbox_id, aud: "https://id.deadsimple.email", iat, exp (at most 10 minutes after iat), jti}` with a `kid` header naming a key enrolled on the inbox. Optional `client_id`, `redirect_uri`, `code_challenge` and `nonce` claims must match the request. Each `jti` is accepted once.
3. **Browser**: no credential at all redirects to `https://app.deadsimple.email/id/consent?request_id=...`, where the account owner picks an inbox and approves.
Success is a 302 to `redirect_uri` with `code` and `state`, or, when the request sends `Accept: application/json`, a 200 JSON body `{redirect_to, code, state}`. A JSON client with no credential gets `401 login_required` rather than a redirect. An unresolvable client_id or a redirect_uri that is not same-origin (open client) or not registered gets a 400 with no redirect.

## Query parameters

- `client_id` string, required
- `redirect_uri` string, required
- `response_type` 'code', required
- `scope` string
- `code_challenge` string, required
- `code_challenge_method` 'S256'
- `state` string
- `nonce` string
- `inbox_id` string
- `login_hint` string
- `assertion` string

## Response `200`

With Accept application/json, the redirect as data.

- object
  - `redirect_to` string
  - `code` string
  - `state` string

## Other responses

- `302`: Redirect to redirect_uri with code and state (or error and state), or to the consent page.
- `400`: invalid_client (never redirected), or a validation error from the API-key path.
- `401`: login_required (JSON client, no credential), or an assertion that failed verification.
- `404`: The API key does not own the requested inbox.

---

[API](https://skmtc.dev/deadsimple/apis/dead-simple-email-api.md) · [All operations](https://skmtc.dev/deadsimple/apis/dead-simple-email-api/llms.txt) · [OpenAPI document](https://skmtc.dev/deadsimple/apis/dead-simple-email-api/revisions/c697881be131?raw)
