Complete Workflow Example
This guide demonstrates the full lifecycle of working with resumes through the API.
Overview
The complete workflow includes:
- Upload a resume file (PDF, DOC, or DOCX)
- Create a resume from structured data
- List all resumes
- Retrieve a specific resume
- Create another resume from retrieved data
- List all resumes again
- Retrieve the newly created resume
- Delete all created resumes
Prerequisites
- Node.js 14 or higher
- Valid API key from your Enhancv business account
- A resume file (PDF, DOC, or DOCX) to upload
Installation
Install the required dependencies:
npm install axios form-data
Complete Example Code
/**
* Complete API Workflow Example
*
* This example demonstrates the full lifecycle of working with resumes through the Enhancv API.
*/
const fs = require("fs");
const path = require("path");
const axios = require("axios");
const FormData = require("form-data");
// Configuration
const API_KEY = "enh_live_your_api_key_here"; // Replace with your actual API key
const BASE_URL = "https://api.enhancv.com/api/v1";
const RESUME_FILE_PATH = path.join(__dirname, "resume.pdf"); // Path to your resume file
// Create axios instance with default config
const api = axios.create({
baseURL: BASE_URL,
headers: {
Authorization: `Bearer ${API_KEY}`,
},
});
// Helper function to make API requests
async function apiRequest(endpoint, options = {}) {
try {
const response = await api({
url: endpoint,
...options,
});
return response.data;
} catch (error) {
const message = error.response?.data?.message || error.message;
throw new Error(`API Error: ${message}`);
}
}
// Sample resume data
const sampleResumeData = {
header: {
name: "John Doe",
title: "Senior Software Engineer",
email: "john.doe@example.com",
phone: "+1 (555) 123-4567",
location: "San Francisco, CA",
website: "https://johndoe.com",
},
sections: {
summaries: {
name: "Professional Summary",
column: 0,
order: 0,
items: [
{
text: "Experienced software engineer with 8+ years of expertise in full-stack development, specializing in scalable web applications and cloud infrastructure.",
},
],
},
experiences: {
name: "Work Experience",
column: 0,
order: 1,
items: [
{
workplace: "Tech Corp",
position: "Senior Software Engineer",
location: "San Francisco, CA",
dateRange: {
fromYear: 2020,
fromMonth: 0,
toYear: 2024,
toMonth: 9,
},
description: "Led development of key features for enterprise platform",
bullets: [
"Led development of microservices architecture serving 10M+ users",
"Reduced API response time by 40% through optimization",
"Mentored team of 5 junior developers",
],
},
{
workplace: "StartupXYZ",
position: "Software Engineer",
location: "New York, NY",
dateRange: {
fromYear: 2016,
fromMonth: 5,
toYear: 2019,
toMonth: 11,
},
bullets: [
"Built RESTful APIs using Node.js and Express",
"Implemented CI/CD pipeline with Docker and Jenkins",
],
},
],
},
educations: {
name: "Education",
column: 0,
order: 2,
items: [
{
institution: "University of Technology",
degree: "Bachelor of Science in Computer Science",
location: "Boston, MA",
dateRange: {
fromYear: 2012,
fromMonth: 8,
toYear: 2016,
toMonth: 4,
},
gpa: "3.8",
maxGpa: "4.0",
},
],
},
industryExperiences: {
name: "Technical Skills",
column: 1,
order: 3,
items: [
{ name: "JavaScript/TypeScript", level: 5, icon: "54-free-code" },
{ name: "Node.js & Express", level: 5 },
{ name: "React & Redux", level: 4 },
{ name: "PostgreSQL & MongoDB", level: 4 },
{ name: "Docker & Kubernetes", level: 3 },
{ name: "AWS & GCP", level: 3 },
],
},
languages: {
name: "Languages",
column: 1,
order: 4,
items: [
{ name: "English", level: 5, levelText: "Native" },
{ name: "Spanish", level: 3, levelText: "Intermediate" },
],
},
certificates: {
name: "Certifications",
column: 1,
order: 5,
items: [
{
title: "AWS Solutions Architect",
issuer: "Amazon Web Services",
},
],
},
findMeOnline: {
name: "Find Me Online",
column: 1,
order: 6,
items: [
{
title: "LinkedIn",
link: "https://linkedin.com/in/johndoe",
icon: "26-linkedin",
},
{
title: "GitHub",
link: "https://github.com/johndoe",
icon: "35-github",
},
],
},
},
title: "John Doe - Senior Software Engineer",
style: {
layout: "double",
colors: ["#000000", "#008CFF"],
fontBody: "lato",
fontHeading: "raleway",
hideBranding: false,
isLetterSize: false,
},
};
// Main workflow
async function runWorkflow() {
const resumeIds = [];
try {
console.log("Starting complete API workflow example...\n");
// Step 1: Upload a resume
console.log("Step 1: Uploading resume file...");
const fileStream = fs.createReadStream(RESUME_FILE_PATH);
const formData = new FormData();
formData.append("file", fileStream, {
filename: path.basename(RESUME_FILE_PATH),
contentType: "application/pdf",
});
const uploadResponse = await axios.post(`${BASE_URL}/resumes/upload`, formData, {
headers: {
Authorization: `Bearer ${API_KEY}`,
...formData.getHeaders(),
},
});
console.log("✓ Resume uploaded successfully!");
console.log(" Resume ID:", uploadResponse.data.id);
resumeIds.push(uploadResponse.data.id);
// Step 2: Create a resume from structured data
console.log("\nStep 2: Creating a resume from structured data...");
const createResponse = await apiRequest("/resumes", {
method: "POST",
data: sampleResumeData,
});
console.log("✓ Resume created successfully!");
console.log(" Resume ID:", createResponse.id);
resumeIds.push(createResponse.id);
// Step 3: List all resumes
console.log("\nStep 3: Listing all resumes...");
const listData = await apiRequest("/resumes");
console.log(`✓ Found ${listData.resumes.length} resume(s):`);
listData.resumes.forEach(resume => {
console.log(` - ${resume.title} (${resume.filename})`);
});
// Step 4: Retrieve the uploaded resume
console.log("\nStep 4: Retrieving uploaded resume details...");
const resumeData = await apiRequest(`/resumes/${resumeIds[0]}`);
console.log("✓ Resume retrieved successfully!");
console.log(" Header:", resumeData.header.name);
console.log(" Sections:", Object.keys(resumeData.sections).length);
// Step 5: Create another resume from the retrieved data
console.log("\nStep 5: Creating another resume from retrieved data...");
const { id, ...dataWithoutId } = resumeData;
// Modify the title to differentiate
dataWithoutId.title = (resumeData.title || "Resume") + " (Copy)";
const createData = await apiRequest("/resumes", {
method: "POST",
data: dataWithoutId,
});
console.log("✓ Third resume created successfully!");
console.log(" Resume ID:", createData.id);
resumeIds.push(createData.id);
// Step 6: List all resumes again
console.log("\nStep 6: Listing all resumes again...");
const listData2 = await apiRequest("/resumes");
console.log(`✓ Found ${listData2.resumes.length} resume(s):`);
listData2.resumes.forEach(resume => {
console.log(` - ${resume.title} (${resume.filename})`);
});
// Step 7: Retrieve the third resume
console.log("\nStep 7: Retrieving the third resume...");
const newResumeData = await apiRequest(`/resumes/${resumeIds[2]}`);
console.log("✓ Third resume retrieved successfully!");
console.log(" Header:", newResumeData.header.name);
console.log(" Sections:", Object.keys(newResumeData.sections).length);
// Step 8: Delete all resumes
console.log("\nStep 8: Cleaning up - deleting all resumes...");
for (const resumeId of resumeIds) {
await apiRequest(`/resumes/${resumeId}`, { method: "DELETE" });
console.log(` ✓ Deleted resume ${resumeId}`);
}
console.log("\n✓ All resumes deleted successfully!");
console.log("\nWorkflow completed successfully!");
} catch (error) {
console.error("\n✗ Error:", error.message);
if (error.response) {
console.error("Response status:", error.response.status);
console.error("Response data:", error.response.data);
}
console.error("\nCleaning up resumes...");
// Try to clean up any created resumes
for (const resumeId of resumeIds) {
try {
await apiRequest(`/resumes/${resumeId}`, { method: "DELETE" });
console.log(` ✓ Deleted resume ${resumeId}`);
} catch {
console.log(` ✗ Failed to delete resume ${resumeId}`);
}
}
process.exit(1);
}
}
// Run the workflow
runWorkflow();
Running the Example
- Save the code above to a file (e.g.,
complete-workflow.js) - Replace
enh_live_your_api_key_herewith your actual API key - Replace
resume.pdfwith the path to your resume file - Run the script:
node complete-workflow.js
Expected Output
Starting complete API workflow example...
Step 1: Uploading resume file...
✓ Resume uploaded successfully!
Resume ID: 64f1a2b3c4d5e6f7g8h9i0j1
Step 2: Creating a resume from structured data...
✓ Resume created successfully!
Resume ID: 64f1a2b3c4d5e6f7g8h9i0j2
Step 3: Listing all resumes...
✓ Found 2 resume(s):
- New Resume (resume.pdf)
- John Doe - Senior Software Engineer (JohnDoeResume.pdf)
Step 4: Retrieving uploaded resume details...
✓ Resume retrieved successfully!
Header: John Smith
Sections: 5
Step 5: Creating another resume from retrieved data...
✓ Third resume created successfully!
Resume ID: 64f1a2b3c4d5e6f7g8h9i0j3
Step 6: Listing all resumes again...
✓ Found 3 resume(s):
- New Resume (resume.pdf)
- John Doe - Senior Software Engineer (JohnDoeResume.pdf)
- New Resume (Copy) (NewResume.pdf)
Step 7: Retrieving the third resume...
✓ Third resume retrieved successfully!
Header: John Smith
Sections: 5
Step 8: Cleaning up - deleting all resumes...
✓ Deleted resume 64f1a2b3c4d5e6f7g8h9i0j1
✓ Deleted resume 64f1a2b3c4d5e6f7g8h9i0j2
✓ Deleted resume 64f1a2b3c4d5e6f7g8h9i0j3
✓ All resumes deleted successfully!
Workflow completed successfully!
Key Points
- Date Ranges: Months use 0-based indexing (0=January, 11=December)
- Authentication: Always include your API key in the
Authorizationheader - File Upload: Use
multipart/form-datafor resume file uploads - Error Handling: The example includes cleanup logic to delete created resumes even if errors occur
- API Key Security: Never commit your API key to version control
Next Steps
- Explore individual endpoint documentation for more details
- Check the Authentication guide for API key management
- Review Error Handling for common error scenarios
- Learn about Rate Limits for production usage