API Design¶
The kairos.api module exposes all core functionality as a versioned REST API following Microsoft REST API Guidelines and RFC 9457 for error responses.
Server¶
| Framework | FastAPI (async, Pydantic v2) |
| ASGI server | uvicorn |
| Default port | 8880 |
| API prefix | /api/v1/ |
| Serialization | JSON (snake_case, matching Python convention) |
| API docs | Scalar at /docs |
Design Principles¶
- RESTful resource-oriented — plural nouns, kebab-case URLs
- No response envelope — success responses return the resource directly
- RFC 9457 errors — all errors return
application/problem+json - Cursor-based pagination — stable ordering, no page skipping issues
- Typed responses — every endpoint has a Pydantic response model
Response Format¶
Success (single resource)¶
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "adzuna",
"title": "Senior Python Developer",
"company": "Acme Corp",
...
}
Success (list)¶
Error (RFC 9457)¶
Content-Type: application/problem+json
{
"type": "https://kairosjobs.app/errors/not-found",
"title": "Resource not found",
"status": 404,
"detail": "Job not found: a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"instance": "/api/v1/jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Validation errors include field-level details:
{
"type": "https://kairosjobs.app/errors/validation-error",
"title": "Validation error",
"status": 422,
"detail": "One or more request parameters are invalid.",
"instance": "/api/v1/jobs/search",
"errors": [
{ "field": "body → keywords", "message": "Field required" }
]
}
Endpoints¶
Jobs¶
| Method | Path | Operation ID | Description |
|---|---|---|---|
POST |
/api/v1/jobs/search |
Jobs.Search |
Search across platforms, save results |
GET |
/api/v1/jobs |
Jobs.List |
List jobs (cursor-paginated, filterable, sortable) |
GET |
/api/v1/jobs/{id} |
Jobs.Get |
Get job details |
POST |
/api/v1/jobs/{id}/fetch-details |
Jobs.FetchDetails |
Re-scrape full description from platform |
DELETE |
/api/v1/jobs/{id} |
Jobs.Delete |
Delete a job (returns 204) |
Config¶
| Method | Path | Operation ID | Description |
|---|---|---|---|
GET |
/api/v1/config |
Config.Get |
Get configuration (sensitive fields removed) |
PATCH |
/api/v1/config |
Config.Update |
Update preference fields (dot notation keys) |
Health¶
| Method | Path | Operation ID | Description |
|---|---|---|---|
GET |
/api/v1/health |
Health.Check |
Server health check |
Planned¶
| Method | Path | Description |
|---|---|---|
POST |
/api/v1/jobs/{id}/analyze |
Trigger JD analysis via LLM |
GET |
/api/v1/jobs/{id}/analysis |
Get analysis results |
POST |
/api/v1/resumes/import |
Import a resume |
GET |
/api/v1/resumes |
List resumes |
POST |
/api/v1/resumes/{id}/tailor |
Tailor resume for a job |
POST |
/api/v1/applications |
Create application record |
GET |
/api/v1/applications |
List applications |
Pagination¶
Cursor-based pagination using (scraped_at, id) composite cursor, base64url-encoded.
Query parameters:
| Param | Default | Description |
|---|---|---|
cursor |
null |
Opaque cursor token from previous next |
page_size |
20 |
Results per page (max 100) |
ordering |
-scraped_at |
Comma-separated fields, prefix - for descending |
Allowed ordering fields: scraped_at, title, company, salary_min, salary_max, platform, status
Example:
Filtering¶
List endpoints support filtering via query parameters:
Error Mapping¶
| Domain Error | HTTP Status | Problem Type |
|---|---|---|
NotFoundError |
404 | /errors/not-found |
ValidationError |
422 | /errors/validation-error |
RequestValidationError |
422 | /errors/validation-error |
ScrapingError |
502 | /errors/upstream-error |
DomainError (base) |
502 | /errors/upstream-error |
Unhandled Exception |
500 | /errors/internal-error |
API Documentation¶
- Scalar UI:
http://localhost:8880/docs - OpenAPI JSON:
http://localhost:8880/openapi.json
Generated from Pydantic models with typed response schemas, field descriptions, and concrete examples.
Authentication¶
Not implemented yet. For local use, the API runs on localhost with no auth. JWT auth is planned for remote/shared deployments.