# Authentication

Two kinds of credential, one header, and a scope vocabulary shared by both. Nothing here ever travels in a URL.

## API keys

Create one in Settings → Developers. The secret is shown once and stored only as a hash, so a lost key is replaced rather than recovered. The prefix names the environment: jat_live_ for your real data, jat_test_ for the sandbox.

- **Presets**: Read-only grants every :read scope. Read and write adds the everyday writes. Full access additionally grants staff changes, billing changes and sandbox resets — the three a person would usually rather do themselves.
- **Restriction**: A key may be confined to one organization. Every organization operation it calls must name that organization in the path, and the check is on the organization id, so a rename does not lift it.
- **Rotation**: Create the replacement, deploy it, then revoke the old one. A revoked key is refused immediately with credential_revoked.

## OAuth 2.1

Use OAuth when your software acts for somebody who is not you. This app is its own authorization server: clients discover it through the protected-resource and authorization-server metadata documents, may register dynamically, and must use the authorization code flow with PKCE. Access tokens are short lived; refresh tokens renew them.

The person approving the request sees the scopes you asked for, in the same words listed below, and may approve a narrower set. Read the granted scopes back from the token response rather than assuming.

## Sending the credential

The only header that authenticates a request:

```
Authorization: Bearer jat_test_…
```

There is no query-string alternative, and no cookie is ever read: the API allows every origin, so honouring a cookie would make it a cross-site request forgery hole.

## Scopes

Scopes are exact: applications:write does not imply applications:read. Every preset grants a resource’s read and write together, which is what keeps that strictness bearable.

- **applications:read**: Read job applications
- **applications:write**: Create, change and delete job applications
- **boards:read**: Read boards and their columns
- **boards:write**: Create, rename and delete boards
- **companies:read**: Read companies
- **companies:write**: Create, change and delete companies
- **contacts:read**: Read contacts and their interactions
- **contacts:write**: Create, change and delete contacts and interactions
- **interviews:read**: Read interviews
- **interviews:write**: Schedule, change and cancel interviews
- **insights:read**: Read job-search insights and statistics
- **imports:write**: Import applications from a spreadsheet
- **resumes:read**: Read resumes
- **resumes:write**: Upload, change and delete resumes
- **profile:read**: Read the account profile and personal information
- **profile:write**: Change the account profile and personal information
- **organizations:read**: Read organizations, rosters and shared boards
- **organizations:write**: Change organization details and cohorts
- **organization_members:write**: Invite, remove and re-role organization staff
- **coach_notes:read**: Read coach notes
- **coach_notes:write**: Write and delete coach notes
- **billing:read**: Read subscriptions, seats and invoices
- **billing:write**: Change subscriptions and purchase seats
- **sandbox:manage**: Reset and reseed the sandbox environment

## Sandbox against live

A sandbox credential acts as a synthetic tenant of its own, so no query it makes can reach a real row and no live credential can reach a sandbox one. Call /me if you are ever unsure which world you are in.