597 lines
14 KiB
Markdown
597 lines
14 KiB
Markdown
# 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.* |