Projects

Update a project

Changed on

Use this endpoint to update a project's fields, link it to an opportunity, and/or add hiring contacts to it.

All fields are optional, but at least one must be provided.

Partial-update semantics for scalar fields (jobRole, ownerEmail, jobDescription, notes, func, seniority, contractType, workMode, salary, expectedFee, hireTarget, visaSupport, public, location, startedAt): omitted fields are left untouched, null clears a nullable field, and a value replaces the stored one. jobRole, ownerEmail, and public cannot be cleared. ownerEmail transfers ownership and must resolve to an existing, active user in the agency (404 otherwise).

Link fields:

  • opportunityId — links the project to an existing opportunity. Only allowed for job_lead projects (state lead); sending it for any other project type returns 422. Linking an opportunity that is already linked to the project is a no-op.
  • companyContactIds — adds hiring contacts to the project. These are CompanyContact junction IDs (the person↔company link, retrievable from companyContact.id on GET /api/v1/people/{id}), not person IDs. Each must belong to the project's companyId — passing a person ID, an ID from another company, or an ID from another agency returns 404. This field is additive only: contacts already linked to the project are skipped (no-op) and existing links are never removed.

Not updatable here: companyId, state, and closedAt — changing the company or closing a project have side effects on linked contacts, opportunities, and candidates and are deliberately excluded from this endpoint.

What you get back: A core snapshot of the updated project (id, jobRole, jobNumber, state), the opportunity it is linked to (null when it has none), and the full list of hiring contact IDs linked to the project after the update — pre-existing links included. Use Get project details to read back all other fields.

patch/api/v1/projects/{id}

Request

Path parameters

idstring uuid required

Project ID

Example:550e8400-e29b-41d4-a716-446655440000

Request body

opportunityIdstring uuid

Opportunity to link this project to. Only allowed for job_lead projects (state lead) — sending it for any other project type returns 422. Linking the same opportunity again is a no-op.

companyContactIdsstring[]

CompanyContact IDs to add as hiring contacts — these are the person↔company link IDs, NOT person IDs. Retrieve a value from the companyContact.id field on GET /api/v1/people/{id}. Each must belong to the project's companyId; passing a person ID (or an ID from another company) returns 404. Additive only: already-linked contacts are skipped (no-op), existing links are never removed. Duplicate entries are silently dropped.

jobRolestring

Job title or role name. Cannot be cleared — omit to leave untouched

ownerEmailstring email

Transfer project ownership. Must be an existing, active user in the agency

jobDescriptionstring nullable

Plain text job description. Send null to clear

notesstring nullable

Internal notes. Send null to clear

funcstring nullable

Job function (e.g. Engineering, Sales). Empty strings are rejected — send null to clear.

seniority'partner' | 'board' | 'founder' | 'cxo' | 'vp' | 'director' | 'manager' | 'senior' | 'middle' | 'junior' | 'training' | 'unpaid' | 'null' nullable

Seniority level

contractType'full_time' | 'part_time' | 'contract' | 'non_exec' | 'null' nullable

Contract type. Send null to clear

workMode'office' | 'hybrid' | 'remote' | 'null' nullable

Work mode. Send null to clear

hireTargetinteger nullable

Number of positions to fill. Send null to clear

visaSupportboolean nullable

Whether visa sponsorship is offered

publicboolean

Whether the project is publicly visible

startedAtstring nullable

Planned or actual start date (YYYY-MM-DD). Must be no earlier than one calendar month ago. Stored as UTC midnight of that calendar day.

Example request

{
  "opportunityId": "550e8400-e29b-41d4-a716-446655440005",
  "companyContactIds": [
    "550e8400-e29b-41d4-a716-446655440006"
  ],
  "jobRole": "Senior Software Engineer",
  "ownerEmail": "owner@agency.com",
  "func": "Engineering",
  "seniority": "senior",
  "salary": {
    "value": "120000-150000",
    "currency": "USD"
  },
  "expectedFee": {
    "value": "25000.00",
    "currency": "USD"
  },
  "hireTarget": 1,
  "location": {
    "name": "London, UK",
    "locality": "London",
    "region": "England",
    "metro": "new york, new york",
    "country": "United Kingdom",
    "streetAddress": "123 Baker Street",
    "addressLine2": "Suite 200",
    "postalCode": "NW1 6XE",
    "raw": "123 Baker Street, London NW1 6XE, United Kingdom",
    "latitude": 51.523767,
    "longitude": -0.158519
  },
  "startedAt": "2026-04-01"
}

Response

Project updated

status'ok' required

Example response

{
  "data": {
    "state": "lead"
  }
}

Changes

    • info

      added the new undefined enum value to the request property

    • info

      added the new undefined enum value to the request property

    • info

      added the new undefined enum value to the request property

    • info

      added the optional property to the response with the status