Employer self-service

Let approved employers claim companies, manage jobs, and review applicants.

Build an employer portal around board.me.companies. Every method is authenticated and scoped to a company membership; public company data remains under board.companies.

Prerequisites

  • board.context().features.employers is true.
  • A server-owned employer session.
  • A protected account area with cache: 'no-store'.
  • UI states for approved, pending_work_email, awaiting_admin, and rejected memberships.

Claim a company

If the membership is pending_work_email, send the verification link. Consume the emailed token with board.auth.verifyWorkEmail — the link carries only a token, so there is no company slug and no board-user session:

Do not unlock management screens until the returned membership is approved.

Create and publish a job

New jobs are held drafts. publish works only while an existing paid window permits it. A held draft that needs billing must use jobs.checkout; branch on checkout, published, pending_approval, or invoice_sent. A free post (or invoice publish-on-issue) returns pending_approval when the board requires free-job approval — show an awaiting-review state. The job’s status becomes pending_approval; like a draft, it is not public, and only the board operator can publish it. Bundle, subscription, and member-credit posts still return published. Never infer publication from a browser redirect.

Load the applicant pipeline

Use the stage order returned by the pipeline. Do not maintain a second ordering model in local storage.

Source candidates onto a job

Talent lists are company-owned saved filters; sourced candidates are per-job membership on an unstaged rail. Save with board.me.companies.sourcedCandidates.add. Convert-on-drop uses board.me.companies.sourcedCandidates.convert — it writes a pipeline application with source sourced, which stays hidden from the candidate until they apply themselves. Do not add a sourced stage to the pipeline rail.

Expected result

An employer sees membership state before any private controls. Approved members can create held drafts, publish or check them out, and read a pipeline whose stages and applicants come from one server response.

Verify the result

  • A pending or rejected membership cannot edit a company or job.
  • Claim confirmation produces the membership state shown in the portal.
  • A created job appears as a draft before publication or checkout.
  • A free checkout on a board that requires free-job approval returns pending_approval, and the job’s status is pending_approval until the operator approves or rejects it.
  • Applicant writes re-read the pipeline after the 204 response.
  • One employer cannot access another company’s private records.

Errors and edge cases

  • Claiming can approve immediately on a domain match or enter a pending state.
  • Work-email links expire after 24 hours.
  • Employer job updates are merge patches; omitted fields remain unchanged.
  • Remote timezone values auto-derive on create when omitted, but do not re-derive on update.
  • Custom stages are capped and protected stages cannot be removed or arbitrarily reordered.

Production cautions

  • Treat applicant data, notes, and signed resume URLs as private.
  • Keep every employer response out of public caches and logs.
  • Use the API’s authorization decision even if the UI already hid a control.
  • Re-read state after void-returning mutations rather than simulating server changes.

Next, add an anonymous purchase path with Job posting and checkout.