# Authentication

# Authentication

Hostex OpenAPI v3 supports two authentication methods. They reach the same
endpoints with the same data — pick based on **who runs the integration**.

| You are…                                                        | Use                                                                                           | Why                                                           |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| A Hostex host integrating against your own account              | [Access Token](#1-access-token)                                                               | Simplest. One header, no flow.                                |
| A software partner building a product used by many Hostex hosts | [OAuth 2.0](#2-oauth-20-bearer-token)                                                         | Each host grants you access without ever sharing their token. |
| An MCP client (Claude Desktop, Cursor, custom LLM agent)        | [OAuth 2.0 + PKCE](https://apidoc.hostex.io/reference/oauth-overview) via the `/mcp` endpoint | The MCP transport itself handles the OAuth handshake.         |

***

## 1. Access Token

### How to obtain

Created by the host inside the Host Portal:

1. Log in at <https://hostex.io/app/dashboard>.
2. Open the [OpenAPI Settings page](https://hostex.io/app/api/open-api).
3. Click **+ Add new**, name the token, pick a scope (read-only / writable).

### How to send

Send the token in the `Hostex-Access-Token` header on every request:

```http
GET /v3/properties HTTP/1.1
Host: api.hostex.io
Hostex-Access-Token: AbCdEf1234567890...
```

Either header form works server-side — the server checks
`Hostex-Access-Token` first and falls back to the standard `Authorization:
Bearer …` header. Prefer `Hostex-Access-Token` for access tokens to avoid
ambiguity with OAuth bearer tokens.

### Scopes

| Scope       | What it can do                                                                |
| ----------- | ----------------------------------------------------------------------------- |
| `read-only` | `GET` endpoints only. Any write returns `401 Not authorized for this action`. |
| `writable`  | Everything. Use sparingly and rotate often.                                   |

Scope is set when the token is created and **cannot be changed** afterwards.
To upgrade, create a new token and revoke the old one.

### Lifetime & revocation

Access tokens **do not expire by themselves**. They live until:

* The host deletes them in the OpenAPI Settings page, or
* The host's subscription expires (in which case requests return
  `420 Subscription expired` even though the token is technically still
  valid; renew the subscription to restore access), or
* The host's Hostex account is deleted.

Always have a graceful re-prompt path in your integration for `401`s.

***

## 2. OAuth 2.0 Bearer Token

If you are a software partner with an approved Hostex `client_id`, you
exchange an authorization code for a Bearer token and send it in the
standard `Authorization` header:

```http
GET /v3/properties HTTP/1.1
Host: api.hostex.io
Authorization: Bearer eyJhbGciOi...
```

OAuth tokens **expire after 7 days**. Use the issued refresh token to mint
a new access token before expiry. See [OAuth Overview](https://apidoc.hostex.io/reference/oauth-overview)
for the full flow, scopes, and refresh semantics.

***

## Identifying which auth mode hit your call

Server-side, both forms resolve to the same `operator` (the Hostex
account that owns the data). Webhooks, audit logs, and error responses
do not distinguish whether you used an access token or an OAuth bearer
token — they are equivalent for the duration of one request.

***

## Common authentication errors

| HTTP body `error_code`                            | When                                                                                               |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `401 Invalid access token`                        | Header missing, token deleted, token does not exist, token belongs to a different host base URL.   |
| `401 Not authorized for this action`              | Token is read-only, request is a write. Issue a writable token.                                    |
| `420 Subscription expired`                        | Underlying Hostex subscription has lapsed. Renew it; the token itself is fine.                     |
| `420 Basic edition does not support this feature` | The host is on Basic edition; OpenAPI access requires Pro.                                         |
| `429 Too many attempts.`                          | OAuth-only: too many invalid `client_secret` / `code_verifier` attempts (>10 in 10 min). Back off. |

> Reminder: HTTP status is always `200`. Always branch on `error_code` from
> the response body. See [Errors](https://apidoc.hostex.io/reference/errors) for the full list.

***

## Security checklist

* Never log full tokens — log only the `request_id` returned by the API.
* Rotate tokens any time a teammate leaves your team.
* Use the read-only scope wherever a `GET` is all you need.
* Send requests over HTTPS only. Hostex rejects plain HTTP.