# API Documentation Structure

## 1. Conventions

- Base URL: `https://{tenant-or-platform-domain}/api/v1`
- Auth: `Authorization: Bearer {jwt}` (except public endpoints: job listing, job detail, agency public profile)
- Content-Type: `application/json`
- Response envelope (JSON:API-inspired, simplified):

```json
{
  "success": true,
  "data": { },
  "meta": { "page": 1, "per_page": 20, "total": 134 },
  "errors": []
}
```

Error response:

```json
{
  "success": false,
  "data": null,
  "errors": [
    { "field": "email", "code": "EMAIL_ALREADY_EXISTS", "message": "Email is already registered." }
  ]
}
```

- Standard HTTP codes: 200/201/204 success, 400 validation, 401 unauthenticated, 403 forbidden (role/permission/plan-limit), 404 not found, 409 conflict, 422 unprocessable, 429 rate-limited, 500 server error.
- Pagination: `?page=1&per_page=20` on all list endpoints, max `per_page=100`.
- Filtering: `?filter[key]=value`, sorting: `?sort=-created_at`.
- Rate limits: default 60 req/min per token, documented per-endpoint if different (e.g. search endpoints 30 req/min).

## 2. Endpoint Groups

### 2.1 Authentication — `/api/v1/auth`
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | `/auth/register/candidate` | Candidate self-registration | Public |
| POST | `/auth/register/agency` | Agency owner registration | Public |
| POST | `/auth/login` | Login, returns access + refresh token | Public |
| POST | `/auth/refresh` | Exchange refresh token for new access token | Public (refresh token) |
| POST | `/auth/logout` | Revoke current token | Bearer |
| POST | `/auth/forgot-password` | Send reset link | Public |
| POST | `/auth/reset-password` | Reset password with token | Public |
| GET | `/auth/me` | Current user profile | Bearer |
| POST | `/auth/2fa/enable` | Enable 2FA | Bearer |
| POST | `/auth/2fa/verify` | Verify 2FA code | Bearer |

### 2.2 Jobs — `/api/v1/jobs`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/jobs` | List/search public jobs (filters: location, category, salary, type, remote) | Public |
| GET | `/jobs/{slug}` | Job detail | Public |
| POST | `/jobs` | Create job | Bearer (Agency Owner/Recruiter, `jobs.create`) |
| PUT | `/jobs/{id}` | Update job | Bearer (`jobs.edit`, own agency) |
| DELETE | `/jobs/{id}` | Delete job | Bearer (`jobs.delete`, own agency) |
| POST | `/jobs/{id}/publish` | Publish draft | Bearer |
| POST | `/jobs/{id}/close` | Close job | Bearer |
| GET | `/jobs/{id}/applications` | List applications for a job | Bearer (own agency) |

### 2.3 Candidates — `/api/v1/candidates`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/candidates/me` | Own candidate profile | Bearer (Candidate) |
| PUT | `/candidates/me` | Update own profile | Bearer (Candidate) |
| POST | `/candidates/me/resume` | Upload resume | Bearer (Candidate) |
| GET | `/candidates/search` | Search candidate DB (filters: skills, experience, education, location, salary, availability) | Bearer (Agency, plan-limited) |
| GET | `/candidates/{id}` | View candidate profile (redacted unless unlocked) | Bearer (Agency) |
| POST | `/candidates/{id}/unlock` | Unlock contact/resume/full profile (credit-gated) | Bearer (Agency) |
| POST | `/candidates/{id}/save` | Save candidate | Bearer (Agency) |
| POST | `/candidates/{id}/tags` | Tag candidate | Bearer (Agency) |

### 2.4 Agencies — `/api/v1/agencies`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/agencies/{slug}` | Public agency profile | Public |
| PUT | `/agencies/me` | Update own agency | Bearer (Agency Owner) |
| POST | `/agencies/me/verification-documents` | Upload verification docs | Bearer (Agency Owner) |
| POST | `/agencies/me/recruiters` | Invite recruiter | Bearer (Agency Owner) |
| DELETE | `/agencies/me/recruiters/{id}` | Remove recruiter | Bearer (Agency Owner) |
| PUT | `/agencies/me/recruiters/{id}/permissions` | Set recruiter permissions | Bearer (Agency Owner) |
| GET | `/agencies/{slug}/reviews` | List company reviews | Public |
| POST | `/agencies/{slug}/reviews` | Submit review | Bearer (Candidate) |

### 2.5 Applications — `/api/v1/applications`
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | `/jobs/{id}/apply` | Apply to job | Bearer (Candidate) |
| GET | `/applications/me` | Candidate's own applications | Bearer (Candidate) |
| GET | `/applications/{id}` | Application detail | Bearer (owner candidate or agency) |
| PUT | `/applications/{id}/status` | Change ATS status | Bearer (Agency, `ats.manage`) |
| POST | `/applications/{id}/notes` | Add internal note | Bearer (Agency) |
| POST | `/applications/{id}/assign` | Assign recruiter | Bearer (Agency Owner) |

### 2.6 Interviews — `/api/v1/interviews`
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | `/applications/{id}/interviews` | Schedule interview | Bearer (Agency) |
| PUT | `/interviews/{id}` | Reschedule | Bearer (Agency) |
| DELETE | `/interviews/{id}` | Cancel | Bearer (Agency) |
| POST | `/interviews/{id}/feedback` | Submit feedback | Bearer (Agency) |
| GET | `/interviews/me` | Candidate's upcoming interviews | Bearer (Candidate) |

### 2.7 Messaging — `/api/v1/conversations`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/conversations` | List own conversations | Bearer |
| POST | `/conversations` | Start conversation (credit-gated for agency) | Bearer |
| GET | `/conversations/{id}/messages` | List messages (paginated) | Bearer (participant) |
| POST | `/conversations/{id}/messages` | Send message | Bearer (participant) |
| POST | `/conversations/{id}/read` | Mark read | Bearer (participant) |

### 2.8 Billing — `/api/v1/billing`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/billing/plans` | List subscription plans | Public |
| POST | `/billing/subscribe` | Subscribe/change plan | Bearer (Agency Owner) |
| GET | `/billing/subscription` | Current subscription + usage | Bearer (Agency Owner) |
| POST | `/billing/credits/purchase` | Buy credits | Bearer (Agency Owner) |
| GET | `/billing/credits` | Credit balance + history | Bearer (Agency Owner) |
| POST | `/billing/wallet/topup` | Top up wallet | Bearer (Agency Owner) |
| GET | `/billing/wallet` | Wallet balance + ledger | Bearer (Agency Owner) |
| GET | `/billing/invoices` | List invoices | Bearer (Agency Owner) |
| GET | `/billing/invoices/{id}/pdf` | Download invoice PDF | Bearer (Agency Owner) |
| POST | `/billing/refund-requests` | Request refund | Bearer (Agency Owner) |
| POST | `/webhooks/{gateway}` | Gateway webhook receiver | Signature-verified, no bearer |

### 2.9 Notifications — `/api/v1/notifications`
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | `/notifications` | List (paginated, filter unread) | Bearer |
| POST | `/notifications/{id}/read` | Mark read | Bearer |
| PUT | `/notifications/preferences` | Update channel preferences | Bearer |

### 2.10 Admin — `/api/v1/admin/*` (Super Admin only)
| Method | Path | Description |
|---|---|---|
| GET | `/admin/agencies` | List/filter all agencies |
| POST | `/admin/agencies/{id}/verify` | Approve/reject verification |
| POST | `/admin/agencies/{id}/suspend` | Suspend agency |
| GET/PUT | `/admin/settings/{group}` | Get/update settings group |
| GET/POST/PUT | `/admin/plans` | Manage subscription plans |
| PUT | `/admin/credit-costs` | Configure credit costs |
| GET | `/admin/reports/{type}` | Platform reports |
| GET | `/admin/audit-logs` | Query audit trail |

## 3. Versioning Policy

- URI versioning (`/v1`, `/v2`) for breaking changes; additive fields never bump version.
- Deprecated endpoints return `Deprecation: true` header + sunset date for 2 release cycles minimum before removal.

## 4. Documentation Delivery

Interactive docs generated from OpenAPI 3.0 spec (`openapi.yaml`, hand-authored per endpoint group above) served via Swagger UI at `/api/docs` — kept in the repo so it version-tracks with route changes; CI fails the build if a route exists without a corresponding OpenAPI path entry.
