Skip to main content
A candidate’s work preferences (locations, compensation, work authorization, and so on) are sent as the required preferences object when you submit a candidate. Afterwards you can read them one at a time or in batches, and replace them per candidate. These are the same values recruiters manage in the app, and they always take precedence in ParaAI matching.

Required fields

Optional fields are salaryMax, ote, roleType, excludedIndustries, and companySizePreferences. The complete list of allowed values for each field is on the replace preferences reference page. visaAuthorization is the only work-authorization field:

Read one candidate

GET /talent-network/candidates/{candidateUserId}/preferences returns { candidateUserId, preferences }.
  • preferences is null when the candidate has none yet. This can happen for candidates who entered the network through a role submission.
  • Any candidate owned by an approved member of your agency is addressable, not just the current membership list. That way you can update off-market or expired candidates before re-enabling them.
  • Another agency’s candidateUserId answers 404, the same as an id that doesn’t exist.

Read many candidates

POST /talent-network/candidates/preferences/lookup reads up to 50 candidates in one call. Reference each candidate by candidateUserId, or by an identity your systems already hold (email or linkedinUrl):
The response is 200 with a results array aligned by index with candidates. Branch on each result’s ok. status is found or not_found.
A found item carries a candidates array, not one candidate. An identity reference resolves to every membership row your agency holds for that person. A candidate owned by two of your recruiters has two independently editable preference rows, each with its own candidateUserId. Read them all, or pick one by candidateUserId.
  • Entries are ordered by ParaAI eligibility expiry, latest first. Rows with no expiry come last.
  • Values are never rejected. An unparseable linkedinUrl, an unknown email, or an item that names no candidate answers not_found at its own index, so one bad CRM row doesn’t cost you the other 49.
  • Only schema violations (a field with the wrong JSON type, or an empty candidateUserId) fail the whole request with 400.
  • Candidates added before the current validation rules may read back null numbers or empty arrays.
There’s no batch write. Use the per-candidate PUT below with the candidateUserId this endpoint returned.

Replace

PUT /talent-network/candidates/{candidateUserId}/preferences is a full replace. The body is the same object submit takes as preferences, sent flat:
  • Validation failures return 400 with per-field errors in details.fieldErrors.
  • Omitted optional fields are cleared: numbers become null and arrays become empty. The write also overwrites values a recruiter set in the app. To keep existing values, read, modify, then write.
  • salaryMax and ote also accept an explicit null, which means the same as omitting them. So the body a GET returns can be sent straight back.
  • The response echoes the stored state and matches a later GET. ParaAI matching and the in-app preferences reflect it immediately.
  • Retries converge, so no Idempotency-Key is needed.