14 KiB
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:
{
"email": "user@example.com",
"password": "SecurePass123!",
"full_name": "John Doe"
}
Response (201):
{
"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 password409- Email already registered
POST /api/v1/auth/login
Authenticate user and return JWT token.
Request:
{
"email": "user@example.com",
"password": "SecurePass123!"
}
Response (200):
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"email": "user@example.com",
"full_name": "John Doe",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
Errors:
401- Invalid credentials400- Missing email or password
GET /api/v1/auth/me
Get current user profile (requires authentication).
Headers: Authorization: Bearer <token>
Response (200):
{
"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
{
"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:
{
"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):
{
"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 charactersrole_title: Required, 1-255 charactersjob_description: Required, minimum 50 charactersjob_url: Optional, valid URL formatpriority_level: Optional, enum:low|medium|high
Errors:
400- Validation errors401- 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):
{
"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 user401- Unauthorized
PUT /api/v1/applications/{application_id}
Update application details.
Headers: Authorization: Bearer <token>
Request:
{
"company_name": "Google Inc.",
"location": "Toronto, ON, Canada",
"priority_level": "medium"
}
Response (200): Updated application object
Errors:
404- Application not found400- Validation errors401- 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 found401- Unauthorized
📄 Documents API
Document Model
{
"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):
{
"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):
{
"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:
{
"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 found400- Validation errors
🤖 AI Processing API
Processing Status Model
{
"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):
{
"message": "Research phase started",
"application_id": "123e4567-e89b-12d3-a456-426614174000",
"estimated_completion": "2025-07-01T10:35:00Z"
}
Errors:
404- Application not found409- Research already completed400- 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):
{
"message": "Resume optimization started",
"application_id": "123e4567-e89b-12d3-a456-426614174000",
"estimated_completion": "2025-07-01T11:05:00Z"
}
Errors:
404- Application not found409- Resume already optimized412- Research phase not completed
POST /api/v1/processing/applications/{application_id}/cover-letter
Start cover letter generation phase.
Headers: Authorization: Bearer <token>
Request:
{
"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):
{
"message": "Cover letter generation started",
"application_id": "123e4567-e89b-12d3-a456-426614174000",
"estimated_completion": "2025-07-01T11:15:00Z"
}
Errors:
404- Application not found409- Cover letter already generated412- Resume optimization not completed
GET /api/v1/processing/applications/{application_id}/status
Get current processing status.
Headers: Authorization: Bearer <token>
Response (200):
{
"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 activeprocessing- AI generation in progresscompleted- Phase completed successfullyfailed- Processing failed with error
👤 User Resumes API
Resume Model
{
"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):
{
"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:
{
"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 characterscontent: Required, minimum 100 charactersfocus_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
{
"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- Success201- Created successfully202- 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 found409- 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 failedAUTHENTICATION_ERROR- Invalid credentialsAUTHORIZATION_ERROR- Insufficient permissionsNOT_FOUND- Resource not foundDUPLICATE_RESOURCE- Resource already existsINVALID_STATE- Operation not valid for current stateEXTERNAL_API_ERROR- Claude/OpenAI API errorPROCESSING_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
offsetfor 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}/statusto 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.