# Profile Module — API Documentation

Base URL: `http://localhost:PORT/api/v1`

---

## Table of Contents
1. [Enum Endpoints](#1-enum-endpoints)
2. [Document Field Endpoints](#2-document-field-endpoints-admin)
3. [Profile Endpoints](#3-profile-endpoints)
4. [My Profiles (User)](#4-get-profilesmy-profiles--own-profiles-user)
5. [Download Document](#5-get-profilesdocumentsdocumentiddownload--download-document)
6. [Download CV](#6-get-profilescvprofileiddownload--download-cv)

> **fieldName auto-generation:** When creating or updating a document field, `fieldName` is never sent by the frontend — the backend generates it from `label` (lowercase + spaces replaced with underscores, special characters stripped). E.g. `"Passport Copy"` → `passport_copy`.

---

## 1. Enum Endpoints

All enum endpoints are **public** (no auth required). Use these to populate dropdowns and checkboxes on the frontend form.

---

### GET `/profiles/enums/:enumName`

**Available enumName values:**

| enumName | Used For |
|---|---|
| `salutations` | Salutation dropdown |
| `immigration-statuses` | Current U.S. Immigration Status dropdown |
| `highest-degrees` | Highest Degree Earned dropdown |
| `industries` | Industry or Field of Study dropdown |
| `immigration-interests` | Immigration interest checkboxes |
| `client-statuses` | Are you a current client? radio |
| `employment-statuses` | Are you currently employed? dropdown |
| `professional-categories` | Professional category radio |
| `submission-types` | Submitting on behalf of? radio |
| `referral-sources` | How did you learn about us? radio |

---

#### GET `/profiles/enums/salutations`

**Response:**
```json
{
  "success": true,
  "message": "salutations list retrieved successfully",
  "data": [
    { "value": "Dr", "label": "Dr" },
    { "value": "Ms", "label": "Ms" },
    { "value": "Mrs", "label": "Mrs" },
    { "value": "Mr", "label": "Mr" },
    { "value": "Prof", "label": "Prof" },
    { "value": "Mx", "label": "Mx" }
  ]
}
```

---

#### GET `/profiles/enums/immigration-interests`

**Response:**
```json
{
  "success": true,
  "message": "immigration-interests list retrieved successfully",
  "data": [
    { "value": "EB_1A_GREEN_CARD", "label": "EB-1A Green Card" },
    { "value": "EB_1B_GREEN_CARD", "label": "EB-1B Green Card" },
    { "value": "EB_2_NIW_GREEN_CARD", "label": "EB-2 NIW Green Card" },
    { "value": "O_1_VISA", "label": "O-1 Visa" },
    { "value": "J_1_WAIVER_SERVICE", "label": "J-1 Waiver Service" },
    { "value": "ADJUSTMENT_OF_STATUS", "label": "Adjustment of Status (I-485)" },
    { "value": "RFE_ASSISTANCE", "label": "RFE Assistance" }
  ]
}
```

---

#### GET `/profiles/enums/immigration-statuses`

**Response:**
```json
{
  "success": true,
  "message": "immigration-statuses list retrieved successfully",
  "data": [
    { "value": "A1_A2", "label": "A-1/A-2" },
    { "value": "B1_B2", "label": "B-1/B-2" },
    { "value": "F1_INCLUDING_OPT_AND_STEM_OPT", "label": "F-1 (Including OPT and STEM OPT)" },
    { "value": "H1B", "label": "H-1B" },
    { "value": "O1", "label": "O-1" },
    { "value": "NOT_IN_THE_US", "label": "Not in the US" },
    { "value": "PERMANENT_RESIDENT_GREEN_CARD_HOLDER", "label": "Permanent Resident/Green Card Holder" },
    { "value": "OTHER", "label": "Other" }
  ]
}
```

---

#### GET `/profiles/enums/highest-degrees`

**Response:**
```json
{
  "success": true,
  "message": "highest-degrees list retrieved successfully",
  "data": [
    { "value": "ASSOCIATES", "label": "Associate's" },
    { "value": "BACHELORS", "label": "Bachelor's" },
    { "value": "MASTERS", "label": "Master's" },
    { "value": "MBA", "label": "M.B.A." },
    { "value": "MBBS", "label": "M.B.B.S." },
    { "value": "DOCTORAL", "label": "Doctoral" },
    { "value": "NO_DEGREE_EARNED", "label": "No Degree Earned" }
  ]
}
```

---

#### GET `/profiles/enums/employment-statuses`

**Response:**
```json
{
  "success": true,
  "message": "employment-statuses list retrieved successfully",
  "data": [
    { "value": "YES_FULL_TIME", "label": "Yes - Full Time" },
    { "value": "YES_PART_TIME", "label": "Yes - Part Time" },
    { "value": "SELF_EMPLOYED", "label": "Self-Employed" },
    { "value": "NO", "label": "No" }
  ]
}
```

---

#### GET `/profiles/enums/professional-categories`

**Response:**
```json
{
  "success": true,
  "message": "professional-categories list retrieved successfully",
  "data": [
    { "value": "RESEARCHER", "label": "Researcher" },
    { "value": "INDUSTRY_PROFESSIONAL", "label": "Industry Professional" },
    { "value": "ARTIST_ATHLETE_ENTERTAINER_CREATIVE", "label": "Artist/Athlete/Entertainer/Creative Professional" },
    { "value": "SOFTWARE_ENGINEER", "label": "Software Engineer" },
    { "value": "START_UP_FOUNDER", "label": "Start-up Founder" },
    { "value": "PILOT", "label": "Pilot" },
    { "value": "OTHER", "label": "Other" }
  ]
}
```

---

#### GET `/profiles/enums/referral-sources`

**Response:**
```json
{
  "success": true,
  "message": "referral-sources list retrieved successfully",
  "data": [
    { "value": "GOOGLE", "label": "Google" },
    { "value": "FACEBOOK", "label": "Facebook" },
    { "value": "BING", "label": "Bing" },
    { "value": "LINKEDIN", "label": "LinkedIn" },
    { "value": "INSTAGRAM", "label": "Instagram" },
    { "value": "TELEGRAM", "label": "Telegram" },
    { "value": "TRACKIT", "label": "Trackit" },
    { "value": "AVVO", "label": "Avvo" },
    { "value": "REFERRAL", "label": "Referral" },
    { "value": "REDDIT", "label": "Reddit" },
    { "value": "OTHER", "label": "Other" }
  ]
}
```

---

#### GET `/profiles/enums/invalid-name` — Error response

**Response `404`:**
```json
{
  "success": false,
  "message": "Enum \"invalid-name\" not found. Available: salutations, immigration-statuses, highest-degrees, industries, immigration-interests, client-statuses, employment-statuses, professional-categories, submission-types, referral-sources",
  "data": null
}
```

---

## 2. Document Field Endpoints (Admin)

Admin controls which document upload fields appear on the profile submission form.

---

### GET `/document-fields` — Public (active fields for form rendering)

**Response:**
```json
{
  "success": true,
  "message": "Active document fields retrieved successfully",
  "data": [
    {
      "id": "df-uuid-1",
      "fieldName": "passport_copy",
      "label": "Passport Copy",
      "description": "Upload a clear copy of your passport (bio page)",
      "isRequired": true,
      "isActive": true,
      "displayOrder": 1,
      "createdAt": "2026-05-29T10:00:00.000Z",
      "updatedAt": "2026-05-29T10:00:00.000Z"
    },
    {
      "id": "df-uuid-2",
      "fieldName": "degree_certificate",
      "label": "Degree Certificate",
      "description": "Upload your highest degree certificate",
      "isRequired": true,
      "isActive": true,
      "displayOrder": 2,
      "createdAt": "2026-05-29T10:00:00.000Z",
      "updatedAt": "2026-05-29T10:00:00.000Z"
    }
  ]
}
```

---

### GET `/document-fields/all` — Admin only

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response:** Same structure as above but includes inactive fields too.

---

### POST `/document-fields` — Admin only

**Headers:**
```
Authorization: Bearer <admin_token>
Content-Type: application/json
```

**Request Body:**
```json
{
  "label": "Recommendation Letter",
  "description": "Upload a letter of recommendation from your employer or professor",
  "isRequired": false,
  "isActive": true,
  "displayOrder": 3
}
```

> Do **not** send `fieldName` — it is auto-generated by the backend from `label`.
> `"Recommendation Letter"` → `recommendation_letter`

**Response `201`:**
```json
{
  "success": true,
  "message": "Document field created successfully",
  "data": {
    "id": "df-uuid-3",
    "fieldName": "recommendation_letter",
    "label": "Recommendation Letter",
    "description": "Upload a letter of recommendation from your employer or professor",
    "isRequired": false,
    "isActive": true,
    "displayOrder": 3,
    "createdAt": "2026-05-29T12:00:00.000Z",
    "updatedAt": "2026-05-29T12:00:00.000Z"
  }
}
```

---

### GET `/document-fields/:id` — Admin only

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response `200`:**
```json
{
  "success": true,
  "message": "Document field retrieved successfully",
  "data": {
    "id": "df-uuid-3",
    "fieldName": "recommendation_letter",
    "label": "Recommendation Letter",
    "description": "Upload a letter of recommendation from your employer or professor",
    "isRequired": false,
    "isActive": true,
    "displayOrder": 3,
    "createdAt": "2026-05-29T12:00:00.000Z",
    "updatedAt": "2026-05-29T12:00:00.000Z"
  }
}
```

---

### PATCH `/document-fields/:id` — Admin only

**Headers:**
```
Authorization: Bearer <admin_token>
Content-Type: application/json
```

**Request Body (all fields optional):**
```json
{
  "label": "Official Recommendation Letter",
  "isRequired": true,
  "isActive": true,
  "displayOrder": 2
}
```

> Updating `label` automatically regenerates `fieldName`.
> `"Official Recommendation Letter"` → `official_recommendation_letter`

**Response `200`:**
```json
{
  "success": true,
  "message": "Document field updated successfully",
  "data": {
    "id": "df-uuid-3",
    "fieldName": "official_recommendation_letter",
    "label": "Official Recommendation Letter",
    "isRequired": true,
    "isActive": true,
    "displayOrder": 2,
    "updatedAt": "2026-05-29T13:00:00.000Z"
  }
}
```

---

### DELETE `/document-fields/:id` — Admin only

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response `200`:**
```json
{
  "success": true,
  "message": "Document field deleted successfully",
  "data": null
}
```

---

## 3. Profile Endpoints

---

### POST `/profiles` — Submit Profile (Auth required: ADMIN or USER)

**Headers:**
```
Authorization: Bearer <user_token or admin_token>
```

**Content-Type:** `multipart/form-data`

> Profile is automatically linked to the authenticated user via `userId` from the JWT token.

#### How file uploads work:
- `cv` → CV/Resume file (PDF, DOC, DOCX, image) — always the same field name
- `{fieldName}` → One file per admin-configured document field, using its `fieldName` as the form key

**Example form fields:**

| Key | Type | Example Value |
|---|---|---|
| `isExistingClient` | string | `"NO"` |
| `salutation` | string | `"Mr"` |
| `firstName` | string | `"John"` |
| `lastName` | string | `"Doe"` |
| `phone` | string | `"+1234567890"` |
| `email` | string | `"john.doe@email.com"` |
| `countryOfBirth` | string | `"India"` |
| `isMarried` | string | `"true"` |
| `hasPriorEB2NIW` | string | `"false"` |
| `immigrationStatus` | string | `"H1B"` |
| `highestDegree` | string | `"MASTERS"` |
| `industryFieldOfStudy` | string | `"SOFTWARE_DEVELOPMENT_ENGINEERING"` |
| `employmentStatus` | string | `"YES_FULL_TIME"` |
| `professionalCategory` | string | `"SOFTWARE_ENGINEER"` |
| `hasPublishedCitedArticles` | string | `"false"` |
| `hasGoogleScholarProfile` | string | `"false"` |
| `lastPublicationDate` | string | `""` (optional) |
| `hasJudgingExperience` | string | `"false"` |
| `submissionType` | string | `"MYSELF"` |
| `additionalComment` | string | `"I have 8 years of experience..."` (optional) |
| `referralSource` | string | `"LINKEDIN"` |
| `interests` | string (JSON) | `'["EB_2_NIW_GREEN_CARD","O_1_VISA"]'` |
| `cv` | file | resume.pdf |
| `passport_copy` | file | passport.jpg |
| `degree_certificate` | file | degree.pdf |

#### JavaScript Fetch Example:
```javascript
const formData = new FormData();

// Text fields
formData.append('isExistingClient', 'NO');
formData.append('salutation', 'Mr');
formData.append('firstName', 'John');
formData.append('lastName', 'Doe');
formData.append('phone', '+1234567890');
formData.append('email', 'john.doe@email.com');
formData.append('countryOfBirth', 'India');
formData.append('isMarried', 'true');
formData.append('hasPriorEB2NIW', 'false');
formData.append('immigrationStatus', 'H1B');
formData.append('highestDegree', 'MASTERS');
formData.append('industryFieldOfStudy', 'SOFTWARE_DEVELOPMENT_ENGINEERING');
formData.append('employmentStatus', 'YES_FULL_TIME');
formData.append('professionalCategory', 'SOFTWARE_ENGINEER');
formData.append('hasPublishedCitedArticles', 'false');
formData.append('hasGoogleScholarProfile', 'false');
formData.append('hasJudgingExperience', 'false');
formData.append('submissionType', 'MYSELF');
formData.append('additionalComment', 'I have 8 years of experience in backend systems.');
formData.append('referralSource', 'LINKEDIN');

// Immigration interests (JSON array string)
formData.append('interests', JSON.stringify(['EB_2_NIW_GREEN_CARD', 'O_1_VISA']));

// Files
formData.append('cv', cvFile);                         // always 'cv'
formData.append('passport_copy', passportFile);        // admin-defined fieldName
formData.append('degree_certificate', degreeFile);     // admin-defined fieldName

const response = await fetch('/api/v1/profiles', {
  method: 'POST',
  body: formData,
});
```

**Response `201`:**
```json
{
  "success": true,
  "message": "Profile submitted successfully",
  "data": {
    "id": "p-uuid-1",
    "userId": null,
    "isExistingClient": "NO",
    "salutation": "Mr",
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+1234567890",
    "email": "john.doe@email.com",
    "countryOfBirth": "India",
    "isMarried": true,
    "hasPriorEB2NIW": false,
    "immigrationStatus": "H1B",
    "highestDegree": "MASTERS",
    "industryFieldOfStudy": "SOFTWARE_DEVELOPMENT_ENGINEERING",
    "employmentStatus": "YES_FULL_TIME",
    "professionalCategory": "SOFTWARE_ENGINEER",
    "hasPublishedCitedArticles": false,
    "hasGoogleScholarProfile": false,
    "lastPublicationDate": null,
    "hasJudgingExperience": false,
    "submissionType": "MYSELF",
    "additionalComment": "I have 8 years of experience in backend systems.",
    "referralSource": "LINKEDIN",
    "cvResumeUrl": "/profile/cv/resume-1717054800000-456789123.pdf",
    "cvFileName": "resume.pdf",
    "createdAt": "2026-05-29T14:00:00.000Z",
    "updatedAt": "2026-05-29T14:00:00.000Z",
    "interests": [
      {
        "id": "pi-uuid-1",
        "interest": "EB_2_NIW_GREEN_CARD",
        "profileId": "p-uuid-1"
      },
      {
        "id": "pi-uuid-2",
        "interest": "O_1_VISA",
        "profileId": "p-uuid-1"
      }
    ],
    "documents": [
      {
        "id": "pd-uuid-1",
        "fileUrl": "/profile/documents/passport-1717054800000-111.jpg",
        "fileName": "passport.jpg",
        "profileId": "p-uuid-1",
        "documentFieldId": "df-uuid-1",
        "createdAt": "2026-05-29T14:00:00.000Z",
        "updatedAt": "2026-05-29T14:00:00.000Z",
        "documentField": {
          "id": "df-uuid-1",
          "fieldName": "passport_copy",
          "label": "Passport Copy",
          "isRequired": true
        }
      },
      {
        "id": "pd-uuid-2",
        "fileUrl": "/profile/documents/degree-1717054800001-222.pdf",
        "fileName": "degree.pdf",
        "profileId": "p-uuid-1",
        "documentFieldId": "df-uuid-2",
        "createdAt": "2026-05-29T14:00:00.000Z",
        "updatedAt": "2026-05-29T14:00:00.000Z",
        "documentField": {
          "id": "df-uuid-2",
          "fieldName": "degree_certificate",
          "label": "Degree Certificate",
          "isRequired": true
        }
      }
    ]
  }
}
```

---

### GET `/profiles` — All Profiles (Admin only)

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response `200`:**
```json
{
  "success": true,
  "message": "Profiles retrieved successfully",
  "data": [
    {
      "id": "p-uuid-1",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@email.com",
      "phone": "+1234567890",
      "immigrationStatus": "H1B",
      "highestDegree": "MASTERS",
      "professionalCategory": "SOFTWARE_ENGINEER",
      "submissionType": "MYSELF",
      "cvResumeUrl": "/profile/cv/resume-1717054800000-456789123.pdf",
      "createdAt": "2026-05-29T14:00:00.000Z",
      "interests": [
        { "id": "pi-uuid-1", "interest": "EB_2_NIW_GREEN_CARD", "profileId": "p-uuid-1" }
      ],
      "documents": [
        {
          "id": "pd-uuid-1",
          "fileUrl": "/profile/documents/passport-1717054800000-111.jpg",
          "fileName": "passport.jpg",
          "documentField": { "fieldName": "passport_copy", "label": "Passport Copy" }
        }
      ]
    }
  ]
}
```

---

### GET `/profiles/:id` — Single Profile (Admin only)

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response `200`:** Same structure as the create response above.

**Response `404`:**
```json
{
  "success": false,
  "message": "Profile not found",
  "data": null
}
```

---

### PATCH `/profiles/:id` — Update Profile (Admin only)

**Content-Type:** `multipart/form-data`

**Headers:**
```
Authorization: Bearer <admin_token>
```

All fields are optional — send only what needs to change.

| Key | Type | Notes |
|---|---|---|
| `firstName` | string | |
| `lastName` | string | |
| `phone` | string | |
| `email` | string | |
| `isExistingClient` | string | `"YES"` \| `"NO"` \| `"UNSURE"` |
| `salutation` | string | `"Mr"` \| `"Ms"` \| etc. |
| `countryOfBirth` | string | |
| `isMarried` | string | `"true"` \| `"false"` |
| `hasPriorEB2NIW` | string | `"true"` \| `"false"` |
| `immigrationStatus` | string | enum value |
| `highestDegree` | string | enum value |
| `industryFieldOfStudy` | string | enum value |
| `employmentStatus` | string | enum value |
| `professionalCategory` | string | enum value |
| `hasPublishedCitedArticles` | string | `"true"` \| `"false"` |
| `hasGoogleScholarProfile` | string | `"true"` \| `"false"` |
| `hasJudgingExperience` | string | `"true"` \| `"false"` |
| `lastPublicationDate` | string | optional |
| `submissionType` | string | `"MYSELF"` \| `"EMPLOYER_SPONSOR"` |
| `additionalComment` | string | optional |
| `referralSource` | string | enum value |
| `interests` | string (JSON) | Replaces all interests. E.g. `'["EB_1A_GREEN_CARD"]'` |
| `cv` | file | Replaces existing CV |
| `{fieldName}` | file | Replaces existing document for that field, or adds a new one |

**Response `200`:**
```json
{
  "success": true,
  "message": "Profile updated successfully",
  "data": {
    "id": "p-uuid-1",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@email.com",
    "cvResumeUrl": "/profile/cv/resume-updated-1717060000000-789.pdf",
    "cvFileName": "resume-updated.pdf",
    "interests": [
      { "id": "pi-uuid-3", "interest": "EB_1A_GREEN_CARD", "profileId": "p-uuid-1" }
    ],
    "documents": [
      {
        "id": "pd-uuid-1",
        "fileUrl": "/profile/documents/passport-new-1717060000000-333.jpg",
        "fileName": "passport-new.jpg",
        "documentFieldId": "df-uuid-1",
        "documentField": { "fieldName": "passport_copy", "label": "Passport Copy" }
      }
    ]
  }
}
```

> **Interests:** If `interests` is sent, all previous interests are deleted and replaced with the new list.
> **Documents:** Each uploaded file is matched by its field name — if a document for that field already exists it is replaced; otherwise a new one is created.

---

### DELETE `/profiles/:id` — Delete Profile (Admin only)

**Headers:**
```
Authorization: Bearer <admin_token>
```

**Response `200`:**
```json
{
  "success": true,
  "message": "Profile deleted successfully",
  "data": null
}
```

---

## File Access URLs

After submission, files are served as static assets:

| File Type | URL Pattern |
|---|---|
| CV / Resume | `http://localhost:PORT/profile/cv/{filename}` |
| Document uploads | `http://localhost:PORT/profile/documents/{filename}` |
| Hero Banner | `http://localhost:PORT/hero-banner/{filename}` |

---

## Typical Frontend Flow

```
1. GET /api/v1/document-fields
   → Render dynamic document upload inputs on form

2. GET /api/v1/profiles/enums/immigration-interests
   GET /api/v1/profiles/enums/immigration-statuses
   GET /api/v1/profiles/enums/highest-degrees
   ... (populate all dropdowns and radio buttons)

3. User logs in and fills form

4. POST /api/v1/profiles (multipart/form-data, requires auth)
   → Profile created and linked to the authenticated user

5. GET /api/v1/profiles/my-profiles
   → User retrieves their own submitted profiles
```

---

## 4. GET `/profiles/my-profiles` — Own Profiles (User)

Returns all profiles linked to the authenticated user's account, ordered newest first.

**Auth:** USER token required

**Headers:**
```
Authorization: Bearer <user_token>
```

**Response `200`:**
```json
{
  "success": true,
  "message": "My profiles retrieved successfully",
  "data": [
    {
      "id": "p-uuid-1",
      "userId": "user-uuid-1",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@email.com",
      "phone": "+1234567890",
      "immigrationStatus": "H1B",
      "highestDegree": "MASTERS",
      "professionalCategory": "SOFTWARE_ENGINEER",
      "submissionType": "MYSELF",
      "cvResumeUrl": "/profile/cv/resume-1717054800000-456789123.pdf",
      "cvFileName": "resume.pdf",
      "createdAt": "2026-05-31T10:00:00.000Z",
      "updatedAt": "2026-05-31T10:00:00.000Z",
      "interests": [
        { "id": "pi-uuid-1", "interest": "EB_2_NIW_GREEN_CARD", "profileId": "p-uuid-1" }
      ],
      "documents": [
        {
          "id": "pd-uuid-1",
          "fileUrl": "/profile/documents/passport-1717054800000-111.jpg",
          "fileName": "passport.jpg",
          "profileId": "p-uuid-1",
          "documentFieldId": "df-uuid-1",
          "documentField": {
            "id": "df-uuid-1",
            "fieldName": "passport_copy",
            "label": "Passport Copy"
          }
        }
      ]
    }
  ]
}
```

> Returns an empty array `[]` if the user has not submitted any profiles yet.

---

## 5. GET `/profiles/documents/:documentId/download` — Download Document

Downloads a specific profile document as a file attachment. Browser will prompt a save dialog.

**Auth:** ADMIN or USER (own document only)

**Headers:**
```
Authorization: Bearer <token>
```

**URL Params:**

| Param | Description |
|---|---|
| `documentId` | The `id` of the `ProfileDocument` record |

**Success `200`:**

Returns the file as a binary download with headers:
```
Content-Disposition: attachment; filename="passport.jpg"
Content-Type: image/jpeg
```

> Use the `id` field from the `documents` array in any profile response.

**Error `403` — accessing another user's document:**
```json
{
  "success": false,
  "message": "You do not have access to this document"
}
```

**Error `404` — document not found:**
```json
{
  "success": false,
  "message": "Document not found"
}
```

**Error `404` — file deleted from disk:**
```json
{
  "success": false,
  "message": "File not found on server"
}
```

#### JavaScript Fetch Example:
```javascript
const response = await fetch(`/api/v1/profiles/documents/${documentId}/download`, {
  headers: { Authorization: `Bearer ${token}` },
});

if (response.ok) {
  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'document';
  a.click();
}
```

---

## 6. GET `/profiles/cv/:profileId/download` — Download CV

Downloads the CV/Resume for a specific profile as a file attachment.

**Auth:** ADMIN or USER (own profile only)

**Headers:**
```
Authorization: Bearer <token>
```

**URL Params:**

| Param | Description |
|---|---|
| `profileId` | The `id` of the `Profile` record |

**Success `200`:**

Returns the file as a binary download with headers:
```
Content-Disposition: attachment; filename="resume.pdf"
Content-Type: application/pdf
```

**Error `403` — accessing another user's CV:**
```json
{
  "success": false,
  "message": "You do not have access to this CV"
}
```

**Error `404` — no CV uploaded:**
```json
{
  "success": false,
  "message": "No CV uploaded for this profile"
}
```

**Error `404` — file deleted from disk:**
```json
{
  "success": false,
  "message": "CV file not found on server"
}
```

#### JavaScript Fetch Example:
```javascript
const response = await fetch(`/api/v1/profiles/cv/${profileId}/download`, {
  headers: { Authorization: `Bearer ${token}` },
});

if (response.ok) {
  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'cv';
  a.click();
}
```
