> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mokaru.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> API keys, scopes, and rate limits

## API Keys

All API requests require an API key passed in the `Authorization` header:

```bash theme={null}
Authorization: Bearer mk_<64 hex characters>
```

### Creating an API Key

1. Go to **Settings → Integrations → API Keys** in the [Mokaru app](https://app.mokaru.ai/settings)
2. Click **Create API key**
3. Give it a name (e.g. "Claude Desktop") and select permissions
4. Copy the key immediately - it's only shown once

<Warning>
  API keys require a **Plus plan**. You can have **1 active key** per account. Revoke the existing key to create a new one.
</Warning>

## Scopes

Each API key has scopes that control what it can access. Most resources have a `:read` and `:write` pair; some have additional verbs.

### Core scopes

| Scope            | Description                             |
| ---------------- | --------------------------------------- |
| `jobs:search`    | Search job listings                     |
| `tracker:read`   | Read your applications                  |
| `tracker:write`  | Create, update, and delete applications |
| `profile:read`   | Read your career profile                |
| `profile:write`  | Update your career profile              |
| `contacts:read`  | Read your contacts                      |
| `contacts:write` | Create, update, and delete contacts     |
| `resume:read`    | List and read resumes                   |
| `resume:write`   | Create, update, and delete resumes      |
| `resume:export`  | Export resumes as PDF                   |

### Resume section scopes

Each section of a resume has its own scope so you can grant fine-grained access.

| Scope                                            | Description                      |
| ------------------------------------------------ | -------------------------------- |
| `experiences:read` / `experiences:write`         | Work experiences                 |
| `education:read` / `education:write`             | Education entries                |
| `skills:read` / `skills:write`                   | Skills                           |
| `summaries:read` / `summaries:write`             | Profile summary variants         |
| `projects:read` / `projects:write`               | Projects                         |
| `certificates:read` / `certificates:write`       | Certificates                     |
| `awards:read` / `awards:write`                   | Awards                           |
| `publications:read` / `publications:write`       | Publications                     |
| `interests:read` / `interests:write`             | Interests                        |
| `custom-sections:read` / `custom-sections:write` | Custom resume sections and items |

If a request requires a scope the key doesn't have, the API returns `403 Forbidden`.

## Rate Limits

Rate limits are **per account** (not per key) using a sliding window. Most endpoints follow a predictable pattern by HTTP method:

| HTTP method                                  | Default limit   |
| -------------------------------------------- | --------------- |
| `GET` (list, e.g. `/v1/contacts`)            | 60 requests/min |
| `GET` (single item, e.g. `/v1/contacts/:id`) | 30 requests/min |
| `POST` (create)                              | 20 requests/min |
| `PATCH` (update)                             | 20 requests/min |
| `DELETE`                                     | 10 requests/min |

A few endpoints deviate from the default:

| Endpoint                         | Limit           |
| -------------------------------- | --------------- |
| `POST /v1/jobs/search`           | 30 requests/min |
| `POST /v1/resume`                | 10 requests/min |
| `POST /v1/resume/:id/export/pdf` | 5 requests/min  |
| `GET /v1/profile`                | 30 requests/min |

Every response includes rate limit headers:

```
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 29
X-RateLimit-Reset: 1710504000000
```

When rate limited, the response status is `429` and the body includes a `Retry-After` indication.

<Note>
  The `/mcp` endpoint uses a slightly different scheme: 100 requests per 10 seconds per IP and 60 per minute per OAuth client, with RFC-draft `RateLimit-*` headers. Tools called via MCP still hit the underlying `/v1/*` rate limits on top of those, so heavy automation can be capped on either layer.
</Note>

## Error Responses

| Status | Meaning                                       |
| ------ | --------------------------------------------- |
| `400`  | Bad request - missing or invalid fields       |
| `401`  | Missing, invalid, expired, or revoked API key |
| `403`  | API key lacks required scope                  |
| `429`  | Rate limit exceeded                           |
| `500`  | Internal server error                         |

All errors return JSON:

```json theme={null}
{
  "error": "Invalid or expired API key"
}
```

## Security

* Keys are **SHA-256 hashed** before storage - plain keys are never stored
* **256-bit entropy** (32 random bytes) - cryptographically secure
* Keys can be **revoked instantly** from Settings
* **Standalone auth** - not tied to your browser session, designed for machine-to-machine access
