round0
API Reference

Candidates API

Create and manage candidates with CV data programmatically

Candidates API

Create and manage candidates with structured CV data for personalized interviews.

Overview

The Candidates API allows you to:

  • Create candidates with detailed CV information
  • Retrieve and update candidate profiles
  • Store work experience, education, skills, and certifications
  • Use candidate data for personalized interview experiences

CV Data Structure

Candidate CV data follows this structure:

{
  summary?: string;                    // Professional summary
  workExperiences: WorkExperience[];   // Employment history
  education: Education[];              // Educational background
  skills: Skill[];                     // Technical and soft skills
  certifications: Certification[];     // Professional certifications
  linkedinUrl?: string;                // LinkedIn profile URL
  portfolioUrl?: string;               // Personal website or portfolio
}

Work Experience

{
  company: string;        // Company name
  title: string;          // Job title
  startDate?: string;     // Start date (YYYY-MM format)
  endDate?: string;       // End date (YYYY-MM format, omit if current)
  isCurrent?: boolean;    // Whether this is current position
  description?: string;   // Role description and achievements
}

Education

{
  institution: string;    // School/university name
  degree?: string;        // Degree type (Bachelor, Master, PhD, etc.)
  field?: string;         // Field of study
  startDate?: string;     // Start date
  endDate?: string;       // Graduation date
}

Skills

{
  name: string;                                    // Skill name
  category?: 'technical' | 'soft' | 'language';   // Skill category
  proficiency?: 'beginner' | 'intermediate' | 'advanced' | 'expert';
}

Certifications

{
  name: string;           // Certification name
  issuer?: string;        // Issuing organization
  issueDate?: string;     // Date issued
  expiryDate?: string;    // Expiration date (if applicable)
  credentialId?: string;  // Credential ID
  credentialUrl?: string; // Verification URL
}

List Candidates

Retrieve a paginated list of all candidates.

GET /api/v1/candidates

Request

Headers:

Authorization: Bearer rz_live_...

Query Parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger50Items per page (max: 100)
searchstring-Filter by candidate name

Response

200 OK:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "John Doe",
      "title": "Senior Developer",
      "cv": {
        "summary": "Experienced software engineer...",
        "workExperiences": [...],
        "education": [...],
        "skills": [...],
        "certifications": []
      },
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 25,
    "total_pages": 1
  }
}

Example

# List all candidates
curl https://rz-app-omega.vercel.app/api/v1/candidates \
  -H "Authorization: Bearer rz_live_..."

# With pagination and search
curl "https://rz-app-omega.vercel.app/api/v1/candidates?page=1&limit=20&search=john" \
  -H "Authorization: Bearer rz_live_..."

Create Candidate

Create a new candidate with optional CV data.

POST /api/v1/candidates

Request

Headers:

Authorization: Bearer rz_live_...
Content-Type: application/json

Body:

{
  "name": "Jane Smith",
  "title": "Product Manager",
  "cv": {
    "summary": "Product manager with 5+ years experience in B2B SaaS",
    "workExperiences": [
      {
        "company": "TechStartup Inc",
        "title": "Senior Product Manager",
        "startDate": "2021-03",
        "isCurrent": true,
        "description": "Lead product strategy for enterprise platform"
      },
      {
        "company": "BigCorp",
        "title": "Product Manager",
        "startDate": "2018-06",
        "endDate": "2021-02",
        "description": "Managed B2B product line with $5M ARR"
      }
    ],
    "education": [
      {
        "institution": "State University",
        "degree": "MBA",
        "field": "Business Administration",
        "endDate": "2018"
      }
    ],
    "skills": [
      { "name": "Product Strategy", "category": "technical", "proficiency": "expert" },
      { "name": "Agile/Scrum", "category": "technical", "proficiency": "advanced" },
      { "name": "Leadership", "category": "soft" }
    ],
    "certifications": [
      {
        "name": "Certified Scrum Product Owner",
        "issuer": "Scrum Alliance",
        "issueDate": "2020-05"
      }
    ],
    "linkedinUrl": "https://linkedin.com/in/janesmith"
  }
}

Parameters:

FieldTypeRequiredDescription
namestringYesCandidate's full name (1-200 characters)
titlestringNoJob title (max 100 characters)
cvobjectNoCV data object (see structure above)

Response

201 Created:

{
  "data": {
    "id": "660f9511-f30c-52e5-b827-557766551111",
    "name": "Jane Smith",
    "title": "Product Manager",
    "cv": {
      "summary": "Product manager with 5+ years experience in B2B SaaS",
      "workExperiences": [...],
      "education": [...],
      "skills": [...],
      "certifications": [...],
      "parsedAt": "2024-01-15T10:30:00Z",
      "parseSource": "manual"
    },
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}

Example

curl -X POST https://rz-app-omega.vercel.app/api/v1/candidates \
  -H "Authorization: Bearer rz_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Smith",
    "title": "Product Manager",
    "cv": {
      "summary": "Product manager with 5+ years experience",
      "skills": [
        { "name": "Product Strategy", "category": "technical" }
      ]
    }
  }'
const response = await fetch('https://rz-app-omega.vercel.app/api/v1/candidates', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Jane Smith',
    title: 'Product Manager',
    cv: {
      summary: 'Product manager with 5+ years experience',
      workExperiences: [
        {
          company: 'TechStartup Inc',
          title: 'Senior Product Manager',
          startDate: '2021-03',
          isCurrent: true
        }
      ],
      skills: [
        { name: 'Product Strategy', category: 'technical', proficiency: 'expert' }
      ]
    }
  })
});

const candidate = await response.json();
console.log('Candidate created:', candidate.data.id);

Get Candidate

Retrieve details for a specific candidate.

GET /api/v1/candidates/:id

Request

Headers:

Authorization: Bearer rz_live_...

Path Parameters:

  • id: Candidate UUID

Response

200 OK:

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Jane Smith",
    "title": "Product Manager",
    "cv": {
      "summary": "Product manager with 5+ years experience in B2B SaaS",
      "workExperiences": [
        {
          "company": "TechStartup Inc",
          "title": "Senior Product Manager",
          "startDate": "2021-03",
          "isCurrent": true,
          "description": "Lead product strategy for enterprise platform"
        }
      ],
      "education": [...],
      "skills": [...],
      "certifications": [...],
      "linkedinUrl": "https://linkedin.com/in/janesmith",
      "parsedAt": "2024-01-15T10:30:00Z",
      "parseSource": "manual"
    },
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z"
  }
}

Errors

404 Not Found:

{
  "error": "Candidate not found"
}

Example

curl https://rz-app-omega.vercel.app/api/v1/candidates/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer rz_live_..."

Update Candidate

Update a candidate's information.

PATCH /api/v1/candidates/:id

Request

Headers:

Authorization: Bearer rz_live_...
Content-Type: application/json

Path Parameters:

  • id: Candidate UUID

Body:

{
  "name": "Jane M. Smith",
  "title": "Senior Product Manager",
  "cv": {
    "summary": "Updated professional summary",
    "workExperiences": [
      {
        "company": "TechStartup Inc",
        "title": "VP of Product",
        "startDate": "2024-01",
        "isCurrent": true
      }
    ],
    "skills": [
      { "name": "Product Strategy", "category": "technical", "proficiency": "expert" },
      { "name": "Team Leadership", "category": "soft", "proficiency": "advanced" }
    ]
  }
}

Parameters (all optional):

FieldTypeDescription
namestringUpdated name (1-200 characters)
titlestring | nullUpdated title (null to remove)
cvobject | nullUpdated CV data (null to remove all CV data)
When updating CV data, the entire CV object is replaced with the new data. To remove CV data completely, pass cv: null.

Response

200 OK:

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Jane M. Smith",
    "title": "Senior Product Manager",
    "cv": {
      "summary": "Updated professional summary",
      "workExperiences": [...],
      "skills": [...],
      "parsedAt": "2024-01-15T11:00:00Z",
      "parseSource": "manual"
    },
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T11:00:00Z"
  }
}

Example

# Update name and title
curl -X PATCH https://rz-app-omega.vercel.app/api/v1/candidates/550e8400... \
  -H "Authorization: Bearer rz_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Senior Product Manager"
  }'

# Remove CV data
curl -X PATCH https://rz-app-omega.vercel.app/api/v1/candidates/550e8400... \
  -H "Authorization: Bearer rz_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "cv": null
  }'

Delete Candidate

Permanently delete a candidate.

DELETE /api/v1/candidates/:id

Request

Headers:

Authorization: Bearer rz_live_...

Path Parameters:

  • id: Candidate UUID

Response

200 OK:

{
  "success": true
}

Errors

404 Not Found:

{
  "error": "Candidate not found"
}

Example

curl -X DELETE https://rz-app-omega.vercel.app/api/v1/candidates/550e8400... \
  -H "Authorization: Bearer rz_live_..."
This action is irreversible. The candidate record will be permanently deleted. Associated interview data will remain but will no longer be linked to a candidate record.

Using Candidates with Invitations

When creating interview invitations, you can include candidate CV data directly in the request. This allows for personalized interview experiences without needing to create a separate candidate record first.

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "candidate_name": "John Doe",
  "candidate_cv": {
    "summary": "Software engineer with 5+ years experience",
    "workExperiences": [
      {
        "company": "Tech Corp",
        "title": "Senior Developer",
        "startDate": "2020-01",
        "isCurrent": true
      }
    ],
    "skills": [
      { "name": "React", "category": "technical" },
      { "name": "TypeScript", "category": "technical" }
    ]
  }
}

See Invitations API for more details.


Errors

Common Error Responses

400 Bad Request - Validation error:

{
  "error": "Validation error",
  "details": [
    {
      "path": ["name"],
      "message": "String must contain at least 1 character(s)"
    }
  ]
}

401 Unauthorized - Invalid API key:

{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key"
  }
}

404 Not Found - Candidate doesn't exist:

{
  "error": "Candidate not found"
}

500 Internal Server Error:

{
  "error": "Failed to create candidate"
}

Best Practices

CV Data Quality

For better interview personalization:

  1. Include work experience: Recent roles help the AI tailor questions
  2. Add relevant skills: Technical skills are especially useful for technical interviews
  3. Provide context: Descriptions of past roles help generate more relevant follow-ups
  4. Keep data structured: Use the proper fields rather than putting everything in summary

Integration Patterns

ATS Integration:

// Sync candidates from your ATS
async function syncCandidateFromATS(atsCandidate) {
  const candidate = await fetch('https://rz-app-omega.vercel.app/api/v1/candidates', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: atsCandidate.name,
      title: atsCandidate.currentTitle,
      cv: {
        summary: atsCandidate.summary,
        workExperiences: atsCandidate.experience.map(exp => ({
          company: exp.company,
          title: exp.title,
          startDate: exp.startDate,
          endDate: exp.endDate,
          isCurrent: exp.isCurrent
        })),
        skills: atsCandidate.skills.map(s => ({
          name: s,
          category: 'technical'
        }))
      }
    })
  }).then(r => r.json());

  // Store mapping for later use
  await db.candidateMappings.create({
    ats_id: atsCandidate.id,
    round0_id: candidate.data.id
  });

  return candidate;
}

Create Interview with Candidate:

// After creating a candidate, create an interview
async function createInterviewForCandidate(candidateId, jobId) {
  // First get the candidate
  const candidate = await fetch(`https://rz-app-omega.vercel.app/api/v1/candidates/${candidateId}`, {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  }).then(r => r.json());

  // Create invitation with candidate's CV
  const interview = await fetch('https://rz-app-omega.vercel.app/api/v1/invitations', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      job_id: jobId,
      candidate_name: candidate.data.name,
      candidate_cv: candidate.data.cv
    })
  }).then(r => r.json());

  return interview;
}

Next Steps