> Index of all guides: https://hither.dev/llms.txt. Agents start at https://hither.dev/skill.md.

# Credentials and REST

For agents and developers choosing how an agent connects, and for clients that call REST instead of MCP. Per-app setup is in [apps](apps.md), lifetimes in [limits](how-it-works.md#limits).

## Which way to connect

1. MCP. Add `https://hither.dev/mcp` to your client and let the client handle sign-in with OAuth. This is the only way to get access that lasts, and the way every [app guide](apps.md) uses.
2. A command-line client, `hither-agent`, is coming. It isn't published yet.
3. REST. For chat interfaces that can make HTTP calls but can't add an MCP server. It gives only anonymous access that ends within 24 hours. [Connect over REST](guest-connections.md) has the steps.

## Credentials

The service issues every credential. An agent never makes its own secret, and nothing needs activating after the person approves.

| Credential | How you get it | Works with | Lifetime |
| --- | --- | --- | --- |
| OAuth access token, `hither_at_…` | Your MCP client signs in | MCP and REST | 1 hour. The client refreshes it until someone revokes the agent. |
| OAuth refresh token, `hither_rt_…` | Issued with the access token | The token endpoint only | Single use. Each refresh returns a new one. |
| REST agent token, `hither_st_…` | `POST /api/agents` | REST | 24 hours. It can't be renewed. |

An agent token identifies one agent and can never approve a computer. Permissions come from each connection. The person revokes an account agent under **Agents** in the [dashboard](https://hither.dev/dashboard), and any connection from the computer's tray icon or setup page.

Never put a token in an MCP client's configuration. Clients that add `https://hither.dev/mcp` sign in by themselves.

## OAuth details for client developers

- Public clients only: an HTTPS client ID metadata document, or dynamic registration at `https://hither.dev/oauth/register` with `token_endpoint_auth_method: "none"`.
- `S256` PKCE, exact registered redirects, and `resource=https://hither.dev/mcp` on authorization, token exchange and refresh.
- Redirects must be public HTTPS or loopback HTTP. Custom schemes, implicit and device-code grants, client secrets and `private_key_jwt` are unsupported.
- A metadata document URL needs a public hostname and a path, with no port, credentials, query, fragment or redirect.
- The consent page offers sign-in or **Continue without an account**. The second path runs a Cloudflare Turnstile check and creates an anonymous agent with temporary access only.
- Refresh one call at a time and save each new refresh token before using it. Reusing a spent one revokes the whole authorization. After an uncertain refresh, sign in again.
- `invalid_grant` with `reconnect_required` means the authorization ended. It says nothing about the computer.
- Errors carry a reference. Share it with the operator, never codes, tokens or full URLs.

A signed-in client can connect before any computer exists and add one with `connect_computer`. An agent without a browser can give the person its authorization URL, but the client must still receive the callback and exchange the code with its PKCE verifier. A remote agent needs a public HTTPS callback or a forwarded port, because a loopback callback lands on the person's machine.

## REST

Send `Authorization: Bearer <agent token>` on every call. A REST agent token and an OAuth access token both work here.

| Call | Endpoint |
| --- | --- |
| Create an anonymous agent | `POST /api/agents`, no token |
| Ask for a computer | `POST /api/connect/request` |
| Check a connection | `GET /api/connections/<connectionId>` |
| List computers | `GET /api/devices` |
| Run an operation | `POST /api/invoke` |
| Recent activity | `GET /api/operations` |
| Resolve an unknown outcome | `POST /api/operations/resolve` |
| Queue work | `POST /api/jobs`, then `/api/jobs/wait`, `/status` or `/cancel` |
| Claim link, anonymous OAuth agents only | `POST /api/agents/claim` with `{}` |
| Ask to keep a connection, account agents only | `POST /api/connections/request-extension` with `{"connectionId": "..."}` |

```json
{
  "deviceId": "<DEVICE_UUID>",
  "operation": "files.read",
  "args": { "path": "~/notes.txt" },
  "requestId": "<FRESH_UUID>"
}
```

Operations follow the same rules as over MCP, described in [use the computer](operations.md). Old endpoints such as `/api/connect/exchange` and `/api/agent-tokens/renew` answer `410 endpoint_removed`.
