TalentSync

AI resume builder and ATS optimizer for job seekers. Tailored resumes, outreach, and interview prep from one profile.

Backend API reference

FastAPI REST surface for TalentSync. Routers mount under /api/v1 and /api/v2, with per-request LLM headers, CORS, and request logging.

Repository layout#

The backend is organized around a modular FastAPI application with separate routers for each functional domain. Routers are mounted under both v1 and v2 prefixes to enable incremental migration. The application logs requests and responses and applies CORS middleware. LLM configuration is injected per request via headers.

Building blocks#

  • FastAPI Application: Centralized routing, middleware, and logging.
  • Routers: Modular endpoints grouped by domain (e.g., ATS, Interview, Cold Mail).
  • LLM Dependency Injection: Per-request LLM creation via headers for flexible provider/model selection.
  • Request/Response Logging: Structured logging of payloads and durations.
  • CORS: Configurable origins for cross-origin requests.

Key characteristics:

  • Versioned endpoints: v1 and v2 coexist for incremental migration.
  • Streaming endpoints: Interview service supports Server-Sent Events (SSE).
  • File-based and text-based variants: Many endpoints offer both multipart/form-data and JSON payloads.

How it fits together#

The API follows a layered architecture:

  • Entry points: Routers define endpoints under /api/v1 and /api/v2.
  • Processing: Route handlers depend on LLM instances resolved per request.
  • Services: Business logic is encapsulated in service modules (referenced by routes).
  • Models: Pydantic schemas define request/response contracts.

Authentication and authorization#

  • Authentication headers:
  • X-LLM-Provider: LLM provider identifier (e.g., openai, anthropic).
  • X-LLM-Model: Model name (e.g., gpt-4o, claude-3.5-sonnet).
  • X-LLM-Key: Decrypted API key.
  • X-LLM-Base: Optional custom base URL.
  • Behavior:
  • If headers are present, a per-request LLM is created using these values.
  • If missing, the server’s default LLM is used.
  • If the custom configuration fails, a 503 error is returned.
  • If the server default LLM is not configured, a 503 error is returned.
  • Role-based access control:
  • No explicit RBAC checks are visible in the documented routes. Access control should be enforced at the application level if required.

Practical example (curl):

  • Set headers for a custom LLM:
  • -H “X-LLM-Provider: openai”
  • -H “X-LLM-Model: gpt-4o”
  • -H “X-LLM-Key: YOUR_API_KEY”

v1 vs v2 API differences and migration paths#

  • Coexistence:
  • v1 endpoints are mounted under /api/v1.
  • v2 endpoints are mounted under /api/v2.
  • Differences observed:
  • ATS Evaluation: v1 exposes file-based and text-based routers; v2 exposes text-based routers.
  • Resume Analysis: v1 has file-based and detailed analysis; v2 adds text-based format-and-analyze and analysis endpoints.
  • Cold Mail: v1 has file-based and editor endpoints; v2 adds text-based generator and editor endpoints.
  • Cover Letter: v1 has generator and editor endpoints; v2 remains unchanged in this file.
  • Hiring Assistant: v1 has file-based endpoint; v2 adds text-based endpoint.
  • Tailored Resume: v1 has file-based and text-based endpoints; v2 mirrors v1.
  • JD Editor: v2 introduces a new endpoint under /api/v2.
  • Migration path:
  • Prefer v2 endpoints for new integrations.
  • Migrate clients incrementally by switching from v1 to v2 equivalents.
  • Validate request/response schemas carefully due to differences in payload formats.

Resume analysis#

  • v1
  • POST /api/v1/resume/analysis
  • Content-Type: multipart/form-data
  • Form fields:
  • file: resume file (PDF, DOC, DOCX, TXT, MD)
  • Response: ResumeUploadResponse
  • POST /api/v1/resume/detailed/analysis/
  • Content-Type: multipart/form-data
  • Form fields:
  • file: resume file
  • Response: ComprehensiveAnalysisResponse
  • v2
  • POST /api/v2/resume/format-and-analyze
  • Content-Type: multipart/form-data
  • Form fields:
  • file: resume file
  • Response: FormattedAndAnalyzedResumeResponse
  • POST /api/v2/resume/analysis
  • Content-Type: application/x-www-form-urlencoded or application/json
  • Form field or JSON field:
  • formated_resume: formatted resume text
  • Response: ComprehensiveAnalysisData

Validation and error handling:

  • File extension validation for resume and job description files.
  • LLM dependency injection via get_request_llm.
  • Error responses for invalid payloads and processing failures.

Example curl (v2 text-based analysis):

  • curl -X POST “{{API_BASE}}/api/v2/resume/analysis”
    -F “formated_resume=”
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

ATS evaluation#

  • v1
  • POST /api/v1/ats/evaluate
  • Content-Type: multipart/form-data or application/json
  • File-based variant:
  • Form fields:
  • resume_file: resume file
  • jd_file: optional job description file (PDF, DOC, DOCX, TXT, MD)
  • jd_text: optional job description text
  • jd_link: optional job description URL
  • company_name: optional
  • company_website: optional
  • Text-based variant:
  • JSON body:
  • resume_text: required
  • Either jd_text or jd_link is required
  • company_name: optional
  • company_website: optional
  • Response: JDEvaluatorResponse
  • v2
  • POST /api/v2/ats/evaluate
  • Content-Type: multipart/form-data or application/json
  • Text-based variant:
  • JSON body:
  • resume_text: required
  • Either jd_text or jd_link is required
  • company_name: optional
  • company_website: optional
  • Response: JDEvaluatorResponse

Validation and error handling:

  • At least one of jd_text or jd_link must be provided.
  • File extension validation for JD files.
  • Error responses for invalid payloads and processing failures.

Example curl (v2 text-based evaluation):

  • curl -X POST “{{API_BASE}}/api/v2/ats/evaluate”
    -H “Content-Type: application/json”
    -d ‘{“resume_text”:“”,“jd_text”:“”}’
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

Interview system (real-time, streaming)#

Endpoints:

  • GET /api/v1/interview/templates
  • Response: templates list
  • GET /api/v1/interview/templates/{template_id}
  • Response: template details
  • POST /api/v1/interview/sessions
  • Request: CreateInterviewRequest
  • Response: InterviewSessionResponse
  • GET /api/v1/interview/sessions/{session_id}
  • Response: InterviewSessionResponse
  • DELETE /api/v1/interview/sessions/{session_id}
  • Response: deletion confirmation
  • GET /api/v1/interview/sessions
  • Query params:
  • status: filter by status (enum)
  • limit: integer
  • Response: sessions array and count
  • POST /api/v1/interview/sessions/{session_id}/answer
  • Request: SubmitAnswerRequest
  • Response: evaluation score, feedback, strengths, improvements, next_question, is_complete
  • GET /api/v1/interview/sessions/{session_id}/summary
  • Response: final score, summary, strengths, weaknesses, recommendations, hiring recommendation
  • GET /api/v1/interview/code/languages
  • Response: supported languages list
  • POST /api/v1/interview/sessions/{session_id}/skip
  • Response: skipped flag, next_question, is_complete
  • POST /api/v1/interview/sessions/{session_id}/events
  • Request: InterviewEventRequest
  • Response: recorded flag, event type, tab_switch_count, warning flag
  • GET /api/v1/interview/sessions/{session_id}/events
  • Query params:
  • event_type: filter by event type (enum)
  • Response: events array and count
  • GET /api/v1/interview/health
  • Response: health status and active session count

Streaming endpoints:

  • POST /api/v1/interview/sessions/{session_id}/answer/stream
  • Media type: text/event-stream
  • Events:
  • chunk: partial evaluation text
  • complete: final result with score and next question
  • error: error message
  • POST /api/v1/interview/sessions/{session_id}/code/stream
  • Media type: text/event-stream
  • Events:
  • execution: code execution result
  • chunk: partial code review text
  • complete: final result with score and next question
  • error: error message
  • POST /api/v1/interview/sessions/{session_id}/summary/stream
  • Media type: text/event-stream
  • Events:
  • chunk: partial summary text
  • complete: final summary with score and recommendation
  • error: error message

Validation and error handling:

  • Enum validation for status and event_type.
  • 404 for missing sessions or templates.
  • 500 for internal errors.
  • SSE generator handles exceptions and emits error events.

Sequence diagram (submit answer stream):

Communication tools#

  • Cold Mail

  • v1

  • POST /api/v1/cold-mail/generator/

  • Content-Type: multipart/form-data

  • Form fields:

  • file: resume file

  • recipient_name, recipient_designation, company_name, sender_name, sender_role_or_goal

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • Response: ColdMailResponse

  • POST /api/v1/cold-mail/editor/

  • Content-Type: multipart/form-data

  • Form fields:

  • file: resume file

  • recipient_name, recipient_designation, company_name, sender_name, sender_role_or_goal

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • generated_email_subject, generated_email_body, edit_inscription

  • Response: ColdMailResponse

  • v2

  • POST /api/v2/cold-mail/generator/

  • Content-Type: application/x-www-form-urlencoded or application/json

  • Form field or JSON field:

  • resume_text: required

  • recipient_name, recipient_designation, company_name, sender_name, sender_role_or_goal

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • Response: ColdMailResponse

  • POST /api/v2/cold-mail/edit/

  • Content-Type: application/x-www-form-urlencoded or application/json

  • Form fields or JSON fields:

  • resume_text: required

  • recipient_name, recipient_designation, company_name, sender_name, sender_role_or_goal

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • generated_email_subject, generated_email_body, edit_inscription

  • Response: ColdMailResponse

  • Cover Letter

  • v1

  • POST /api/v1/cover-letter/generator/

  • Content-Type: application/x-www-form-urlencoded or application/json

  • Form fields or JSON fields:

  • resume_text: required

  • recipient_name, company_name, sender_name, sender_role_or_goal

  • job_description: optional

  • jd_url: optional

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • language: default “en”

  • Response: CoverLetterResponse

  • POST /api/v1/cover-letter/edit/

  • Content-Type: application/x-www-form-urlencoded or application/json

  • Form fields or JSON fields:

  • resume_text: required

  • recipient_name, company_name, sender_name, sender_role_or_goal

  • job_description: optional

  • jd_url: optional

  • key_points_to_include: optional

  • additional_info_for_llm: optional

  • company_url: optional

  • generated_cover_letter: required

  • edit_instructions: required

  • language: default “en”

  • Response: CoverLetterResponse

Validation and error handling:

  • Form-based endpoints accept multipart/form-data.
  • JSON-based endpoints accept application/json.
  • LLM dependency injection via get_request_llm.

Example curl (v2 cold mail generator):

  • curl -X POST “{{API_BASE}}/api/v2/cold-mail/generator/”
    -F “resume_text=”
    -F “recipient_name=John Doe”
    -F “recipient_designation=Hiring Manager”
    -F “company_name=Acme Inc.”
    -F “sender_name=Alice”
    -F “sender_role_or_goal=Recruiter”
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

Hiring assistant#

  • v1
  • POST /api/v1/hiring-assistant/
  • Content-Type: multipart/form-data
  • Form fields:
  • file: resume file
  • role: required
  • questions: required
  • company_name: required
  • user_knowledge: optional
  • company_url: optional
  • word_limit: optional (integer)
  • Response: HiringAssistantResponse
  • v2
  • POST /api/v2/hiring-assistant/
  • Content-Type: application/x-www-form-urlencoded or application/json
  • Form field or JSON field:
  • resume_text: required
  • role: required
  • questions: required
  • company_name: required
  • user_knowledge: optional
  • company_url: optional
  • word_limit: optional (integer)
  • Response: HiringAssistantResponse

Validation and error handling:

  • word_limit constrained to a reasonable range (as defined in the service).
  • LLM dependency injection via get_request_llm.

Example curl (v2 hiring assistant):

  • curl -X POST “{{API_BASE}}/api/v2/hiring-assistant/”
    -F “resume_text=”
    -F “role=Software Engineer”
    -F “questions=Explain OOP principles”
    -F “company_name=Tech Corp”
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

Tailored resume#

  • v1
  • POST /api/v1/resume/tailor
  • Content-Type: multipart/form-data
  • Form fields:
  • resume_file: required
  • job_role: required
  • company_name: optional
  • company_website: optional
  • job_description: optional
  • Response: ComprehensiveAnalysisResponse
  • v2
  • POST /api/v2/resume/tailor
  • Content-Type: application/json
  • JSON body:
  • resume_text: required
  • job_role: required
  • company_name: optional
  • company_website: optional
  • job_description: optional
  • Response: ComprehensiveAnalysisResponse

Validation and error handling:

  • LLM dependency injection via get_request_llm.

Example curl (v2 tailored resume):

  • curl -X POST “{{API_BASE}}/api/v2/resume/tailor”
    -H “Content-Type: application/json”
    -d ‘{“resume_text”:“”,“job_role”:“Senior Developer”}’
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

JD editor (v2)#

  • POST /api/v2/resume/edit-by-jd
  • Content-Type: application/json
  • Request: JDEditRequest
  • Response: JDEditResponse

Validation and error handling:

  • LLM dependency injection via get_request_llm.

Example curl:

  • curl -X POST “{{API_BASE}}/api/v2/resume/edit-by-jd”
    -H “Content-Type: application/json”
    -d ‘{“resume_data”:{…},“jd_text”:“”}’
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

Resume improvement and enrichment#

  • Resume Improvement
  • POST /api/v1/resume/improve
  • Content-Type: application/json
  • Request: ResumeImproveRequest
  • Response: ResumeImproveResponse
  • POST /api/v2/resume/improve
  • Same contract as v1
  • Resume Enrichment
  • POST /api/v1/resume/enrichment/analyze
  • Content-Type: application/json
  • Request: AnalyzeRequest
  • Response: AnalysisResponse
  • POST /api/v1/resume/enrichment/improve
  • Content-Type: application/json
  • Request: EnhanceRequest
  • Response: EnhancementPreview
  • POST /api/v1/resume/enrichment/refine
  • Content-Type: application/json
  • Request: RefineEnhancementsRequest
  • Response: EnhancementPreview
  • POST /api/v1/resume/enrichment/apply
  • Content-Type: application/json
  • Request: ApplyEnhancementsRequest
  • Response: updated resume object
  • POST /api/v1/resume/enrichment/regenerate
  • Content-Type: application/json
  • Request: RegenerateRequest
  • Response: RegenerateResponse
  • POST /api/v1/resume/enrichment/apply-regenerated
  • Content-Type: application/json
  • Request: ApplyRegeneratedRequest
  • Response: updated resume object

Validation and error handling:

  • LLM dependency injection via get_request_llm for generation endpoints.
  • Some apply endpoints may return 409 when applying regenerated items conflicts occur.

Example curl (v1 enrichment analyze):

  • curl -X POST “{{API_BASE}}/api/v1/resume/enrichment/analyze”
    -H “Content-Type: application/json”
    -d ‘{“resume_data”:{…}}’
    -H “X-LLM-Provider: openai”
    -H “X-LLM-Model: gpt-4o”
    -H “X-LLM-Key: YOUR_API_KEY”

Additional v1 endpoints#

  • Tips
  • GET /api/v1/tips
  • Response: TipsResponse
  • LinkedIn
  • GET /api/v1/linkedin/posts
  • POST /api/v1/linkedin/posts
  • Responses: PostGenerationResponse, GitHubAnalysisResponse
  • Postgres
  • GET /api/v1/postgres/stats
  • Response: stats object
  • LLM Config
  • GET /api/v1/llm/config
  • PUT /api/v1/llm/config
  • Response: config object

Note: These endpoints are included in the v1 mount but are not covered in detail here due to scope limitations.

Dependencies#

External dependencies relevant to the API:

  • FastAPI: Web framework and ASGI server.
  • LangChain stack: LLM integrations (OpenAI, Anthropic, Google, Ollama).
  • SSE support: sse-starlette for streaming responses.
  • Pydantic: Data validation and serialization.
  • Cryptography: Encryption utilities.
  • PDF/text processing: pymupdf, pymupdf4llm.

Performance#

  • Streaming responses: Use SSE endpoints for long-running evaluations to reduce latency and improve UX.
  • LLM cost and latency: Configure appropriate providers and models via headers to balance quality and speed.
  • File processing: Large resume/JD files may increase processing time; consider compression and validation.
  • Pagination and filtering: Use query parameters (e.g., limit, status) to constrain result sets for list endpoints.

Troubleshooting#

Common issues:

  • LLM configuration errors:
  • Symptom: 503 error indicating LLM service not configured.
  • Resolution: Set up default LLM provider or pass custom headers (X-LLM-Provider, X-LLM-Model, X-LLM-Key).
  • Invalid payloads:
  • Symptom: 400 error for missing required fields or invalid combinations.
  • Resolution: Ensure either jd_text or jd_link is provided for ATS evaluation; validate form fields for multipart endpoints.
  • Session not found:
  • Symptom: 404 error for interview endpoints.
  • Resolution: Verify session_id exists and is correct.
  • Unsupported file types:
  • Symptom: 400 error for JD files with unsupported extensions.
  • Resolution: Use allowed extensions (PDF, DOC, DOCX, TXT, MD).

Logging:

  • Requests and responses are logged with request IDs for tracing.

Appendix#

Request/Response schemas overview#

  • Common schemas:
  • WorkExperienceEntry, ProjectEntry, PublicationEntry, PositionOfResponsibilityEntry, CertificationEntry, AchievementEntry, SkillProficiency, LanguageEntry, EducationEntry, ErrorResponse
  • ATS Evaluator:
  • ATSEvaluationRequest, ATSEvaluationResponse, JDEvaluatorRequest, JDEvaluatorResponse
  • Interview:
  • InterviewQuestion, CandidateProfile, InterviewConfig, InterviewSession, InterviewEvent, CreateInterviewRequest, SubmitAnswerRequest, CodeExecutionRequest, InterviewEventRequest, InterviewSessionResponse, EvaluationResult, CodeExecutionResult
  • Resume Analysis:
  • ComprehensiveAnalysisData, ComprehensiveAnalysisResponse, FormattedAndAnalyzedResumeResponse, ResumeUploadResponse