initial setup
This commit is contained in:
597
docs/api_specification.md
Normal file
597
docs/api_specification.md
Normal file
@@ -0,0 +1,597 @@
|
||||
# JobForge MVP - API Specification
|
||||
|
||||
**Version:** 1.0.0 MVP
|
||||
**Base URL:** `http://localhost:8000`
|
||||
**Target Audience:** Backend Developers
|
||||
**Last Updated:** July 2025
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Authentication
|
||||
|
||||
### Overview
|
||||
- **Method:** JWT Bearer tokens
|
||||
- **Token Expiry:** 24 hours
|
||||
- **Refresh:** Not implemented in MVP (re-login required)
|
||||
- **Header Format:** `Authorization: Bearer <jwt_token>`
|
||||
|
||||
### Authentication Endpoints
|
||||
|
||||
#### POST /api/v1/auth/register
|
||||
Register new user account.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "SecurePass123!",
|
||||
"full_name": "John Doe"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"email": "user@example.com",
|
||||
"full_name": "John Doe",
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"token_type": "bearer"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `400` - Invalid email format or weak password
|
||||
- `409` - Email already registered
|
||||
|
||||
#### POST /api/v1/auth/login
|
||||
Authenticate user and return JWT token.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "SecurePass123!"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"email": "user@example.com",
|
||||
"full_name": "John Doe",
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"token_type": "bearer"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401` - Invalid credentials
|
||||
- `400` - Missing email or password
|
||||
|
||||
#### GET /api/v1/auth/me
|
||||
Get current user profile (requires authentication).
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"email": "user@example.com",
|
||||
"full_name": "John Doe",
|
||||
"created_at": "2025-07-01T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401` - Invalid or expired token
|
||||
|
||||
---
|
||||
|
||||
## 📋 Applications API
|
||||
|
||||
### Application Model
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"name": "google_senior_developer_2025_07_01",
|
||||
"company_name": "Google",
|
||||
"role_title": "Senior Developer",
|
||||
"job_url": "https://careers.google.com/jobs/123",
|
||||
"job_description": "We are looking for...",
|
||||
"location": "Toronto, ON",
|
||||
"priority_level": "high",
|
||||
"status": "draft",
|
||||
"research_completed": false,
|
||||
"resume_optimized": false,
|
||||
"cover_letter_generated": false,
|
||||
"created_at": "2025-07-01T10:00:00Z",
|
||||
"updated_at": "2025-07-01T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Application Endpoints
|
||||
|
||||
#### POST /api/v1/applications
|
||||
Create new job application.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"company_name": "Google",
|
||||
"role_title": "Senior Developer",
|
||||
"job_description": "We are looking for an experienced developer...",
|
||||
"job_url": "https://careers.google.com/jobs/123",
|
||||
"location": "Toronto, ON",
|
||||
"priority_level": "high",
|
||||
"additional_context": "Found through LinkedIn, know someone there"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"name": "google_senior_developer_2025_07_01",
|
||||
"company_name": "Google",
|
||||
"role_title": "Senior Developer",
|
||||
"job_url": "https://careers.google.com/jobs/123",
|
||||
"job_description": "We are looking for an experienced developer...",
|
||||
"location": "Toronto, ON",
|
||||
"priority_level": "high",
|
||||
"status": "draft",
|
||||
"research_completed": false,
|
||||
"resume_optimized": false,
|
||||
"cover_letter_generated": false,
|
||||
"created_at": "2025-07-01T10:00:00Z",
|
||||
"updated_at": "2025-07-01T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Validation Rules:**
|
||||
- `company_name`: Required, 1-255 characters
|
||||
- `role_title`: Required, 1-255 characters
|
||||
- `job_description`: Required, minimum 50 characters
|
||||
- `job_url`: Optional, valid URL format
|
||||
- `priority_level`: Optional, enum: `low|medium|high`
|
||||
|
||||
**Errors:**
|
||||
- `400` - Validation errors
|
||||
- `401` - Unauthorized
|
||||
|
||||
#### GET /api/v1/applications
|
||||
List user's applications.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Query Parameters:**
|
||||
- `status`: Filter by status (optional)
|
||||
- `priority`: Filter by priority level (optional)
|
||||
- `limit`: Number of results (default: 50, max: 100)
|
||||
- `offset`: Pagination offset (default: 0)
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"applications": [
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"name": "google_senior_developer_2025_07_01",
|
||||
"company_name": "Google",
|
||||
"role_title": "Senior Developer",
|
||||
"status": "research_complete",
|
||||
"priority_level": "high",
|
||||
"research_completed": true,
|
||||
"resume_optimized": false,
|
||||
"cover_letter_generated": false,
|
||||
"created_at": "2025-07-01T10:00:00Z",
|
||||
"updated_at": "2025-07-01T11:30:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"limit": 50,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /api/v1/applications/{application_id}
|
||||
Get specific application details.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):** Full application object (see Application Model above)
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found or not owned by user
|
||||
- `401` - Unauthorized
|
||||
|
||||
#### PUT /api/v1/applications/{application_id}
|
||||
Update application details.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"company_name": "Google Inc.",
|
||||
"location": "Toronto, ON, Canada",
|
||||
"priority_level": "medium"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):** Updated application object
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found
|
||||
- `400` - Validation errors
|
||||
- `401` - Unauthorized
|
||||
|
||||
#### DELETE /api/v1/applications/{application_id}
|
||||
Delete application and all associated documents.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (204):** No content
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found
|
||||
- `401` - Unauthorized
|
||||
|
||||
---
|
||||
|
||||
## 📄 Documents API
|
||||
|
||||
### Document Model
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"application_id": "456e7890-e89b-12d3-a456-426614174000",
|
||||
"document_type": "research_report",
|
||||
"content": "# Research Report\n\n## Job Analysis\n...",
|
||||
"created_at": "2025-07-01T10:30:00Z",
|
||||
"updated_at": "2025-07-01T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Document Endpoints
|
||||
|
||||
#### GET /api/v1/applications/{application_id}/documents
|
||||
Get all documents for an application.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"research_report": {
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"content": "# Research Report\n\n## Job Analysis\n...",
|
||||
"created_at": "2025-07-01T10:30:00Z",
|
||||
"updated_at": "2025-07-01T10:30:00Z"
|
||||
},
|
||||
"optimized_resume": {
|
||||
"id": "234e5678-e89b-12d3-a456-426614174000",
|
||||
"content": "# John Doe\n\n## Experience\n...",
|
||||
"created_at": "2025-07-01T11:00:00Z",
|
||||
"updated_at": "2025-07-01T11:00:00Z"
|
||||
},
|
||||
"cover_letter": null
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /api/v1/applications/{application_id}/documents/{document_type}
|
||||
Get specific document.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**URL Parameters:**
|
||||
- `document_type`: enum: `research_report|optimized_resume|cover_letter`
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"application_id": "456e7890-e89b-12d3-a456-426614174000",
|
||||
"document_type": "research_report",
|
||||
"content": "# Research Report\n\n## Job Analysis\n...",
|
||||
"created_at": "2025-07-01T10:30:00Z",
|
||||
"updated_at": "2025-07-01T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `404` - Document not found or application not owned by user
|
||||
|
||||
#### PUT /api/v1/applications/{application_id}/documents/{document_type}
|
||||
Update document content (user editing).
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"content": "# Updated Research Report\n\n## Job Analysis\nUpdated content..."
|
||||
}
|
||||
```
|
||||
|
||||
**Response (200):** Updated document object
|
||||
|
||||
**Validation:**
|
||||
- `content`: Required, minimum 10 characters
|
||||
|
||||
**Errors:**
|
||||
- `404` - Document or application not found
|
||||
- `400` - Validation errors
|
||||
|
||||
---
|
||||
|
||||
## 🤖 AI Processing API
|
||||
|
||||
### Processing Status Model
|
||||
```json
|
||||
{
|
||||
"application_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"current_phase": "research",
|
||||
"status": "processing",
|
||||
"progress": 0.6,
|
||||
"estimated_completion": "2025-07-01T10:35:00Z",
|
||||
"error_message": null
|
||||
}
|
||||
```
|
||||
|
||||
### Processing Endpoints
|
||||
|
||||
#### POST /api/v1/processing/applications/{application_id}/research
|
||||
Start research phase processing.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (202):**
|
||||
```json
|
||||
{
|
||||
"message": "Research phase started",
|
||||
"application_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"estimated_completion": "2025-07-01T10:35:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found
|
||||
- `409` - Research already completed
|
||||
- `400` - Application not in correct state
|
||||
|
||||
#### POST /api/v1/processing/applications/{application_id}/resume
|
||||
Start resume optimization phase.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Requirements:** Research phase must be completed
|
||||
|
||||
**Response (202):**
|
||||
```json
|
||||
{
|
||||
"message": "Resume optimization started",
|
||||
"application_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"estimated_completion": "2025-07-01T11:05:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found
|
||||
- `409` - Resume already optimized
|
||||
- `412` - Research phase not completed
|
||||
|
||||
#### POST /api/v1/processing/applications/{application_id}/cover-letter
|
||||
Start cover letter generation phase.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"additional_context": "I'm particularly interested in their AI/ML projects. I have experience with TensorFlow and PyTorch."
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements:** Resume optimization must be completed
|
||||
|
||||
**Response (202):**
|
||||
```json
|
||||
{
|
||||
"message": "Cover letter generation started",
|
||||
"application_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"estimated_completion": "2025-07-01T11:15:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `404` - Application not found
|
||||
- `409` - Cover letter already generated
|
||||
- `412` - Resume optimization not completed
|
||||
|
||||
#### GET /api/v1/processing/applications/{application_id}/status
|
||||
Get current processing status.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"application_id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"current_phase": "resume",
|
||||
"status": "completed",
|
||||
"progress": 1.0,
|
||||
"completed_at": "2025-07-01T11:05:00Z",
|
||||
"error_message": null
|
||||
}
|
||||
```
|
||||
|
||||
**Status Values:**
|
||||
- `idle` - No processing active
|
||||
- `processing` - AI generation in progress
|
||||
- `completed` - Phase completed successfully
|
||||
- `failed` - Processing failed with error
|
||||
|
||||
---
|
||||
|
||||
## 👤 User Resumes API
|
||||
|
||||
### Resume Model
|
||||
```json
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"name": "Technical Resume",
|
||||
"content": "# John Doe\n\n## Technical Skills\n...",
|
||||
"focus_area": "software_development",
|
||||
"is_primary": true,
|
||||
"created_at": "2025-07-01T09:00:00Z",
|
||||
"updated_at": "2025-07-01T09:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Resume Endpoints
|
||||
|
||||
#### GET /api/v1/resumes
|
||||
Get user's resume library.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"resumes": [
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"name": "Technical Resume",
|
||||
"focus_area": "software_development",
|
||||
"is_primary": true,
|
||||
"created_at": "2025-07-01T09:00:00Z",
|
||||
"updated_at": "2025-07-01T09:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/resumes
|
||||
Upload new resume to library.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "Management Resume",
|
||||
"content": "# John Doe\n\n## Leadership Experience\n...",
|
||||
"focus_area": "management",
|
||||
"is_primary": false
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):** Created resume object
|
||||
|
||||
**Validation:**
|
||||
- `name`: Required, 1-255 characters
|
||||
- `content`: Required, minimum 100 characters
|
||||
- `focus_area`: Optional, enum: `software_development|management|data_science|consulting|other`
|
||||
|
||||
#### GET /api/v1/resumes/{resume_id}
|
||||
Get specific resume details.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (200):** Full resume object
|
||||
|
||||
#### PUT /api/v1/resumes/{resume_id}
|
||||
Update resume content.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Request:** Same as POST
|
||||
|
||||
**Response (200):** Updated resume object
|
||||
|
||||
#### DELETE /api/v1/resumes/{resume_id}
|
||||
Delete resume from library.
|
||||
|
||||
**Headers:** `Authorization: Bearer <token>`
|
||||
|
||||
**Response (204):** No content
|
||||
|
||||
**Errors:**
|
||||
- `409` - Cannot delete primary resume if it's the only one
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Error Handling
|
||||
|
||||
### Standard Error Response
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Invalid input data",
|
||||
"details": {
|
||||
"company_name": ["This field is required"],
|
||||
"job_description": ["Must be at least 50 characters"]
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-07-01T10:00:00Z",
|
||||
"path": "/api/v1/applications"
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP Status Codes
|
||||
- `200` - Success
|
||||
- `201` - Created successfully
|
||||
- `202` - Accepted (async processing started)
|
||||
- `204` - No content (successful deletion)
|
||||
- `400` - Bad request (validation errors)
|
||||
- `401` - Unauthorized (invalid/missing token)
|
||||
- `403` - Forbidden (valid token, insufficient permissions)
|
||||
- `404` - Not found
|
||||
- `409` - Conflict (duplicate email, invalid state transition)
|
||||
- `412` - Precondition failed (phase not completed)
|
||||
- `422` - Unprocessable entity (semantic errors)
|
||||
- `500` - Internal server error
|
||||
|
||||
### Error Codes
|
||||
- `VALIDATION_ERROR` - Input validation failed
|
||||
- `AUTHENTICATION_ERROR` - Invalid credentials
|
||||
- `AUTHORIZATION_ERROR` - Insufficient permissions
|
||||
- `NOT_FOUND` - Resource not found
|
||||
- `DUPLICATE_RESOURCE` - Resource already exists
|
||||
- `INVALID_STATE` - Operation not valid for current state
|
||||
- `EXTERNAL_API_ERROR` - Claude/OpenAI API error
|
||||
- `PROCESSING_ERROR` - AI processing failed
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Development Notes
|
||||
|
||||
### Rate Limiting (Future)
|
||||
- Not implemented in MVP
|
||||
- Will be added in Phase 2 for SaaS
|
||||
|
||||
### Pagination
|
||||
- Default limit: 50
|
||||
- Maximum limit: 100
|
||||
- Use `offset` for pagination
|
||||
|
||||
### Content Validation
|
||||
- Job description: 50-10000 characters
|
||||
- Resume content: 100-50000 characters
|
||||
- Names: 1-255 characters
|
||||
- URLs: Valid HTTP/HTTPS format
|
||||
|
||||
### Background Processing
|
||||
- AI operations run asynchronously
|
||||
- Use `/processing/applications/{id}/status` to check progress
|
||||
- Frontend should poll every 2-3 seconds during processing
|
||||
|
||||
---
|
||||
|
||||
*This API specification covers all endpoints required for MVP implementation. Use the OpenAPI documentation at `/docs` for interactive testing during development.*
|
||||
Reference in New Issue
Block a user