How to build employer self-service workflows

Create and claim companies, manage jobs, applicants, pipeline stages, billing, and messaging.

Employer routes sit behind a board-user session and company authorization. Load company membership first and pass the current access token per call. Never use a shared stateful SDK client for employer requests.

Create the employer home

ts
const options = {
cache: 'no-store' as const,
headers: { authorization: `Bearer ${accessToken}` },
};
const companies = await board.me.companies.list(options);

If the user has no company, offer create, search, or claim paths according to board.context().features. Creating a company and claiming an existing company are distinct workflows; do not guess ownership from an email domain.

Verify work email and claims

Use board.me.companies.workEmail.verify to request a challenge and confirm to complete it. Use claim and cancelClaim for the company ownership workflow. Show the returned status and next action; do not treat a pending claim as active employer access.

Manage company jobs

ts
const { data: memberships } = await board.me.companies.list(options);
const membership = memberships.find(
({ company }) => company.slug === requestedCompanySlug,
);
if (!membership || membership.status !== 'approved' || !membership.company.slug) {
throw new Response('Forbidden', { status: 403 });
}
const companySlug = membership.company.slug;
const [jobs, billingOptions] = await Promise.all([
board.me.companies.jobs.list(companySlug, { limit: 50 }, options),
board.me.companies.billingOptions.list(companySlug, options),
]);

The membership list is the source of truth for companies this user can manage; board.me.companies.search({ q }) is only for finding a company to claim. Create or update a draft, complete checkout when required, then publish. Unpublish and delete are separate actions with separate availability. After a mutation, reload the job from board.me.companies.jobs.retrieve and render the server state.

Build the applicant pipeline

Use board.me.companies.applicants.list for the current queue. Move or reject one applicant with the focused methods; use bulk methods only after the user selects explicit application IDs. Pipeline stage create, update, reorder, and remove calls are company-scoped and private.

Add employer messaging

Start an application conversation with board.me.conversations.startAboutApplication. List and reply through the conversation namespace. Keep unread counts and archive state sourced from the API; do not infer them from the messages currently rendered.

Verify the employer journey

  1. Test a user with no company, a pending claim, an active company, and access to two companies.
  2. Attempt a cross-company job and applicant request and confirm the API denies it.
  3. Create a draft, complete the required billing step, publish it, and verify it appears in the public jobs API.
  4. Move an applicant through reordered stages and reload the pipeline after each mutation.
  5. Start a conversation about an application and confirm only authorized company members can read it.

Continue with Monetization and paywalls to connect plans, posting products, and candidate access.