> ## Documentation Index
> Fetch the complete documentation index at: https://careerk.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Get My Matches

> Retrieve job matches for the authenticated job seeker with filtering and pagination

## Endpoint

```
GET /api/v1/job-seekers/me/matches
```

**Base URL**: `http://localhost:3000/api/v1`

<Note>This endpoint requires **authentication** and **Job Seeker role**.</Note>

## Authentication

Include the access token in the Authorization header:

```bash theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
```

## Query Parameters

<ParamField query="type" type="string" optional default="all">
  Filter matches by source type. Options: `all`, `direct`, `scraped`
</ParamField>

<ParamField query="search" type="string" optional>
  Full-text search across title, description, company name, and skills
</ParamField>

<ParamField query="jobType" type="enum" optional>
  Filter by job type. Options: `FULL_TIME`, `PART_TIME`, `CONTRACT`, `FREELANCE`, `INTERNSHIP`
</ParamField>

<ParamField query="location" type="string" optional>
  Filter by location (partial match, case-insensitive)
</ParamField>

<ParamField query="workPreference" type="enum" optional>
  Work preference filter (direct jobs only). Options: `REMOTE`, `ONSITE`, `HYBRID`
</ParamField>

<ParamField query="experienceLevel" type="enum" optional>
  Experience level filter (direct jobs only). Options: `ENTRY`, `JUNIOR`, `MID`, `SENIOR`, `LEAD`, `MANAGER`
</ParamField>

<ParamField query="salaryMin" type="number" optional>
  Minimum salary filter (direct jobs only)
</ParamField>

<ParamField query="salaryMax" type="number" optional>
  Maximum salary filter (direct jobs only)
</ParamField>

<ParamField query="source" type="string" optional>
  Scraped job source filter (scraped only). e.g. `LinkedIn`, `Indeed`
</ParamField>

<ParamField query="minScore" type="number" optional>
  Minimum match score threshold (0-100)
</ParamField>

<ParamField query="page" type="number" optional default="1" min="1">
  Page number for pagination
</ParamField>

<ParamField query="limit" type="number" optional default="10" min="1">
  Number of items per page
</ParamField>

## Examples

### Scraped Matches

```bash theme={null}
# All scraped matches
GET /api/v1/job-seekers/me/matches?type=scraped

# Search keyword
GET /api/v1/job-seekers/me/matches?type=scraped&search=react

# Search + location
GET /api/v1/job-seekers/me/matches?type=scraped&search=python&location=remote

# Job type filter
GET /api/v1/job-seekers/me/matches?type=scraped&jobType=FULL_TIME

# By source website
GET /api/v1/job-seekers/me/matches?type=scraped&source=LinkedIn

# Min score only
GET /api/v1/job-seekers/me/matches?type=scraped&minScore=80

# Combined: search + jobType + minScore
GET /api/v1/job-seekers/me/matches?type=scraped&search=devops&jobType=CONTRACT&minScore=60

# Paginated (page 3, 20 per page)
GET /api/v1/job-seekers/me/matches?type=scraped&page=3&limit=20
```

### Direct Matches

```bash theme={null}
# All direct matches
GET /api/v1/job-seekers/me/matches?type=direct

# Search keyword (title, desc, company, skills)
GET /api/v1/job-seekers/me/matches?type=direct&search=typescript

# Search + location
GET /api/v1/job-seekers/me/matches?type=direct&search=senior&location=new+york

# Job type
GET /api/v1/job-seekers/me/matches?type=direct&jobType=FULL_TIME

# Work preference
GET /api/v1/job-seekers/me/matches?type=direct&workPreference=REMOTE

# Experience level
GET /api/v1/job-seekers/me/matches?type=direct&experienceLevel=SENIOR

# Salary range
GET /api/v1/job-seekers/me/matches?type=direct&salaryMin=80000&salaryMax=150000

# Min score
GET /api/v1/job-seekers/me/matches?type=direct&minScore=90

# Location + jobType + experienceLevel + salary
GET /api/v1/job-seekers/me/matches?type=direct&location=remote&jobType=FULL_TIME&experienceLevel=MID&salaryMin=60000

# Everything combined
GET /api/v1/job-seekers/me/matches?type=direct&search=react&jobType=FULL_TIME&workPreference=REMOTE&experienceLevel=SENIOR&salaryMin=100000&salaryMax=200000&minScore=70&page=1&limit=20
```

### All (merged)

```bash theme={null}
# Search across both sources
GET /api/v1/job-seekers/me/matches?search=python&jobType=FULL_TIME&location=remote&minScore=70
```

## Response

### Success Response (200 OK)

```json theme={null}
{
  "success": true,
  "data": {
    "matches": [
      {
        "id": "acecb886-2c2d-4e5b-9b5d-49d1e4c5ca7b",
        "type": "scraped",
        "title": "Junior Full Stack Developer",
        "description": "We are looking for a junior full stack developer...",
        "location": "Bournemouth, England, United Kingdom",
        "salary": null,
        "jobType": "FULL_TIME",
        "companyName": "Haystack",
        "sourceUrl": "https://uk.linkedin.com/jobs/view/junior-full-stack-developer-at-haystack-4407798645",
        "source": "LinkedIn",
        "postedAt": "2026-05-04T23:43:55.307Z",
        "skills": [
          { "skillId": "uuid1", "name": "TypeScript" },
          { "skillId": "uuid2", "name": "React" },
          { "skillId": "uuid3", "name": "Next.js" }
        ],
        "matchScore": 88
      },
      {
        "id": "d86db67d-451b-4189-a49f-7c3bca8c6a99",
        "type": "direct",
        "title": "Mid-Level Backend Developer",
        "description": "We are looking for a motivated backend developer...",
        "requirements": null,
        "responsibilities": null,
        "location": "Alexandria, Egypt",
        "salaryMin": 12000,
        "salaryMax": 20000,
        "jobType": "FULL_TIME",
        "workPreference": "REMOTE",
        "experienceLevel": "MID",
        "company": {
          "id": "4ea0d345-f379-4d02-8b89-db49b62abdcc",
          "name": "Tech Corp",
          "logoUrl": null,
          "industry": "Technology"
        },
        "publishedAt": "2026-04-18T19:16:22.638Z",
        "applicants": 0,
        "skills": [
          { "skillId": "uuid1", "name": "Node.js" },
          { "skillId": "uuid2", "name": "Docker" }
        ],
        "matchScore": 64
      }
    ],
    "total": 2,
    "page": 1,
    "limit": 10,
    "totalPages": 1
  },
  "message": "Job seeker matches retrieved successfully",
  "meta": {
    "timestamp": "2026-06-03T18:09:04.738Z",
    "path": "/job-seekers/me/matches",
    "method": "GET"
  }
}
```

### Response Fields

<ResponseField name="matches" type="array">
  List of job matches sorted by match score (highest first). Each object contains the full job
  details with `matchScore` as a flat field. The shape differs based on `type`.

  <Expandable title="Common Fields (all types)">
    <ResponseField name="id" type="string">
      Unique job identifier (UUID).
    </ResponseField>

    <ResponseField name="type" type="enum">
      `"direct"` or `"scraped"`.
    </ResponseField>

    <ResponseField name="title" type="string">
      Job title.
    </ResponseField>

    <ResponseField name="description" type="string">
      Job description.
    </ResponseField>

    <ResponseField name="location" type="string">
      Job location.
    </ResponseField>

    <ResponseField name="jobType" type="enum">
      `FULL_TIME`, `PART_TIME`, `CONTRACT`, etc.
    </ResponseField>

    <ResponseField name="skills" type="array">
      List of required skills with `skillId` and `name`.
    </ResponseField>

    <ResponseField name="matchScore" type="number">
      Match score percentage (0–100). Higher scores indicate better compatibility.
    </ResponseField>
  </Expandable>

  <Expandable title="Direct Job Extra Fields (type: direct)">
    <ResponseField name="requirements" type="string | null">
      Job requirements.
    </ResponseField>

    <ResponseField name="responsibilities" type="string | null">
      Job responsibilities.
    </ResponseField>

    <ResponseField name="salaryMin" type="number">
      Minimum salary.
    </ResponseField>

    <ResponseField name="salaryMax" type="number">
      Maximum salary.
    </ResponseField>

    <ResponseField name="workPreference" type="enum">
      `REMOTE`, `ONSITE`, `HYBRID`.
    </ResponseField>

    <ResponseField name="experienceLevel" type="enum">
      `JUNIOR`, `MID`, `SENIOR`, etc.
    </ResponseField>

    <ResponseField name="publishedAt" type="string">
      Publication date (ISO 8601).
    </ResponseField>

    <ResponseField name="applicants" type="number">
      Number of applicants so far.
    </ResponseField>

    <ResponseField name="company" type="object">
      Company details: `id`, `name`, `logoUrl`, `industry`.
    </ResponseField>
  </Expandable>

  <Expandable title="Scraped Job Extra Fields (type: scraped)">
    <ResponseField name="salary" type="string | null">
      Salary as a raw string from the source.
    </ResponseField>

    <ResponseField name="companyName" type="string">
      Company name.
    </ResponseField>

    <ResponseField name="sourceUrl" type="string">
      Original URL of the job posting.
    </ResponseField>

    <ResponseField name="source" type="string">
      Platform the job was scraped from (e.g. `"LinkedIn"`).
    </ResponseField>

    <ResponseField name="postedAt" type="string">
      Posting date from the source (ISO 8601).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total" type="number">
  Total number of matches available.
</ResponseField>

<ResponseField name="page" type="number">
  Current page number.
</ResponseField>

<ResponseField name="limit" type="number">
  Number of items per page.
</ResponseField>

<ResponseField name="totalPages" type="number">
  Total number of pages available.
</ResponseField>

***

## Job Details Response by Source

<Info>
  When fetching details for a specific match, the shape of the `data` object differs depending on
  the `jobSource`.
</Info>

### Direct Job (`jobSource: "DIRECT"`)

```json theme={null}
{
  "success": true,
  "data": {
    "id": "6cc9f0af-10c0-4998-b252-fc6c52394759",
    "type": "direct",
    "title": "Senior Backend Engineer",
    "description": "We are looking for an experienced backend engineer...",
    "requirements": "5+ years experience in Node.js",
    "responsibilities": "Design and implement APIs, mentor junior developers",
    "location": "Cairo, Egypt",
    "salaryMin": 15000,
    "salaryMax": 25000,
    "jobType": "FULL_TIME",
    "workPreference": "REMOTE",
    "experienceLevel": "SENIOR",
    "publishedAt": "2026-02-22T14:51:00.000Z",
    "company": {
      "id": "uuid",
      "name": "Tech Corp",
      "logoUrl": null,
      "industry": "Technology"
    },
    "source": "direct",
    "skills": [
      { "skillId": "uuid1", "name": "Node.js" },
      { "skillId": "uuid2", "name": "TypeScript" },
      { "skillId": "uuid3", "name": "PostgreSQL" }
    ],
    "applicants": 1
  }
}
```

<Expandable title="Direct Job Fields">
  <ResponseField name="id" type="string">
    Unique job identifier (UUID).
  </ResponseField>

  <ResponseField name="type" type="string">
    Always `"direct"` for this source.
  </ResponseField>

  <ResponseField name="title" type="string">
    Job title.
  </ResponseField>

  <ResponseField name="description" type="string">
    Full job description.
  </ResponseField>

  <ResponseField name="requirements" type="string">
    Job requirements.
  </ResponseField>

  <ResponseField name="responsibilities" type="string">
    Job responsibilities.
  </ResponseField>

  <ResponseField name="location" type="string">
    Job location.
  </ResponseField>

  <ResponseField name="salaryMin" type="number">
    Minimum salary.
  </ResponseField>

  <ResponseField name="salaryMax" type="number">
    Maximum salary.
  </ResponseField>

  <ResponseField name="jobType" type="enum">
    `FULL_TIME`, `PART_TIME`, `CONTRACT`, etc.
  </ResponseField>

  <ResponseField name="workPreference" type="enum">
    `REMOTE`, `ONSITE`, `HYBRID`.
  </ResponseField>

  <ResponseField name="experienceLevel" type="enum">
    `JUNIOR`, `MID`, `SENIOR`, etc.
  </ResponseField>

  <ResponseField name="publishedAt" type="string">
    Publication date (ISO 8601).
  </ResponseField>

  <ResponseField name="company" type="object">
    Company details: `id`, `name`, `logoUrl`, `industry`.
  </ResponseField>

  <ResponseField name="skills" type="array">
    List of required skills with `skillId` and `name`.
  </ResponseField>

  <ResponseField name="applicants" type="number">
    Number of applicants so far.
  </ResponseField>
</Expandable>

***

### Scraped Job (`jobSource: "SCRAPED"`)

```json theme={null}
{
  "success": true,
  "data": {
    "id": "scr_1234567890",
    "type": "scraped",
    "title": "Senior Software Engineer",
    "description": "We are looking for a senior software engineer...",
    "location": "Remote",
    "salary": "$120,000 - $150,000 per year",
    "jobType": "FULL_TIME",
    "companyName": "Tech Corp",
    "sourceUrl": "https://example.com/jobs/123",
    "postedAt": "2024-01-15T10:00:00Z",
    "source": "LinkedIn",
    "skills": [{ "skillId": "uuid1", "name": "TypeScript" }]
  }
}
```

<Expandable title="Scraped Job Fields">
  <ResponseField name="id" type="string">
    Unique scraped job identifier (prefixed with `scr_`).
  </ResponseField>

  <ResponseField name="type" type="string">
    Always `"scraped"` for this source.
  </ResponseField>

  <ResponseField name="title" type="string">
    Job title.
  </ResponseField>

  <ResponseField name="description" type="string">
    Job description.
  </ResponseField>

  <ResponseField name="location" type="string">
    Job location.
  </ResponseField>

  <ResponseField name="salary" type="string">
    Salary as a raw string from the source (not structured).
  </ResponseField>

  <ResponseField name="jobType" type="enum">
    `FULL_TIME`, `PART_TIME`, `CONTRACT`, etc.
  </ResponseField>

  <ResponseField name="companyName" type="string">
    Company name (no structured company object).
  </ResponseField>

  <ResponseField name="sourceUrl" type="string">
    Original URL of the job posting.
  </ResponseField>

  <ResponseField name="postedAt" type="string">
    Posting date from the source (ISO 8601).
  </ResponseField>

  <ResponseField name="source" type="string">
    Platform the job was scraped from (e.g. `"LinkedIn"`).
  </ResponseField>

  <ResponseField name="skills" type="array">
    List of required skills with `skillId` and `name`.
  </ResponseField>
</Expandable>

***

## Error Responses

### 401 Unauthorized

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Unauthorized",
    "statusCode": 401,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/job-seekers/me/matches",
    "method": "GET",
    "details": "Unauthorized"
  }
}
```

### 403 Forbidden

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Forbidden resource",
    "statusCode": 403,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/job-seekers/me/matches",
    "method": "GET",
    "details": "Forbidden"
  }
}
```

### 400 Bad Request - Validation Error

```json theme={null}
{
  "success": false,
  "error": {
    "message": ["type must be one of: all, direct, scraped"],
    "statusCode": 400,
    "timestamp": "2026-04-23T20:00:00.000Z",
    "path": "/job-seekers/me/matches",
    "method": "GET",
    "details": "Bad Request"
  }
}
```

## Notes

<Info>
  **Match Score Calculation**: Matches are sorted by match score in descending order. Jobs with
  higher scores appear first in the results.
</Info>

<Tip>
  **Keyword Search**: Use the `search` parameter to find matches across title, description, company
  name, and skills. Direct job searches also include requirements and responsibilities.
</Tip>

<Tip>
  **Direct Job Filters**: Parameters `workPreference`, `experienceLevel`, `salaryMin`, and
  `salaryMax` only apply to direct job matches. Scraped jobs do not have these structured fields.
</Tip>

<Tip>
  **Scraped Source Filter**: Use `source=LinkedIn` (or `Indeed`, etc.) with `type=scraped` to
  narrow results to a specific job board.
</Tip>
