Wbcom Designs WP Career Board Pro Docs
← Back to product Buy Now

Getting Started

Install, license, and activate WP Career Board Pro.

Introduction to WP Career Board Pro

WP Career Board Pro adds resumes, custom fields, a hiring pipeline, paid job posting, multiple boards, job alerts, a job map and optional AI tools to the free WP Career Board plugin. Use this page to find the feature you want, then follow its link.

What you can do with Pro

Let candidates build resumes

Candidates build structured, multi-section resumes on your site. Employers can view them, and candidates can print them or download a PDF. → Resume builder

Add your own fields

Add custom fields to jobs, companies, resumes and application forms without code. Field types include text, dropdowns, checkboxes, dates and file links. → Field Builder

Move applicants through hiring stages

Employers drag applicants across the stages of a Kanban board. Each job row on the employer dashboard has a Pipeline button that opens its board. → Application pipeline

Charge credits to post jobs

Employers spend credits to post. They can buy credits with Stripe or PayPal, or through WooCommerce, WooCommerce Subscriptions, WooCommerce Memberships, PMPro or MemberPress. Posting is free until you set a credit cost on a board. → Credit system

Run more than one board

Run several boards from one site. Each board has its own pipeline stages, credit cost, moderation setting and currency. Visitors can narrow the job list to one board. → Multi-board

Send job alerts

Candidates save a search and get an email when matching jobs are posted. Each alert is instant, daily or weekly. → Job alerts

Show jobs on a map

Show jobs that have a location on an interactive map. When a job list is on the same page, the map narrows to the jobs in the list. → Job map

Use AI tools (optional)

Connect OpenAI, Anthropic Claude or a self-hosted Ollama server. Candidates can search jobs in plain language, see job matches and draft a cover letter. Employers can rank applicants by fit and get short applicant summaries, and can draft a job description on the job form. → AI features

Let employers find candidates

The Find Candidates page lists candidates who chose to list their resume, with search and filters. Under Settings > Resumes, choose who can browse it: anyone, logged-in members, or approved employers. → Find Candidates

Add Pro blocks and shortcodes

Pro adds blocks to the block inserter, and each one has a matching shortcode for page builders. → Pro blocks reference

Requirement: the free plugin

WP Career Board Pro needs the free WP Career Board plugin installed and active. It adds to Free and does not work on its own.

Licensing

Your license gives you automatic updates and support from wbcomdesigns.com. Every Pro feature on your site keeps working without a valid license. The one exception is the companion mobile app connection, which needs a valid license. See License activation.

Installing WP Career Board Pro

You can install Pro like any other WordPress plugin. Install and activate the free WP Career Board plugin first.

Before you start

  1. WP Career Board (free) is installed and active.
  2. Your site runs WordPress 6.9 or higher.
  3. Your server runs PHP 8.1 or higher.
  4. You have the Pro plugin zip file from your purchase.

Install Pro

  1. In your WordPress admin, go to Plugins > Add New > Upload Plugin.
  2. Choose the Pro zip file and click Install Now.
  3. Click Activate Plugin.

What happens when you activate

  • Pro checks that Free is active and new enough. If not, Pro turns itself off and shows an error.
  • Pro sets up what it needs to store resumes, custom fields, job alerts, pipeline stages, notifications and credits.
  • The Pro blocks appear in the block editor, and each has a matching shortcode.
  • New tabs appear under Career Board > Settings. See Pro settings reference.

After activation

If Free's setup wizard is already finished, you land on a short Pro setup wizard. It asks for your license key, sets the low balance alert and creates the Find Candidates and Job Map pages if they are missing. See License activation.

Activation errors

  • "WP Career Board Pro requires WP Career Board (Free) to be installed and active." Install and activate Free, then activate Pro.
  • "WP Career Board Pro requires WP Career Board (Free) ... or newer. You have ... installed. Please update Free first." The message names the version Pro needs and the one you have. Update Free, then activate Pro.

For other problems see Troubleshooting.

License activation

You can activate your license to get automatic updates and support for WP Career Board Pro. The license does not switch any website feature on or off. Every Pro feature works with no license, an expired license or an invalid key. The one exception is the companion mobile app connection, which stays off until the license is valid.

Find your license key

Your license key is in your purchase confirmation email. You can also find it in your account at wbcomdesigns.com.

Activate with the setup wizard

After you activate Pro on a site that has already finished Free's setup wizard, you land on a short Pro wizard. Its steps are:

  1. License - paste the key and click Activate & Continue. Click Skip for now to do this later.
  2. How Employers Pay - set the Low Balance Alert level (employers get an email when their balance drops to it) and see whether credit sales are ready. If they are not, the step tells you to turn on Stripe or PayPal and add a credit pack, or map a WooCommerce, PMPro or MemberPress product.
  3. Pro Pages - creates the Find Candidates and Job Map pages. This step shows only when one of them is missing.

On a brand new install, Pro adds the License and How Employers Pay steps to Free's own setup wizard.

Activate from Settings

  1. Go to Career Board > Settings > License.
  2. Paste the key into the license key field.
  3. Click the activate button next to it.

The License status card then shows the product, the status, the expiry date (or Lifetime) and how many sites use the license (for example "2 of 5 sites", or "Unlimited"). The Usage Data setting controls whether the updater shares usage data with wbcomdesigns.com.

License statuses

Status Meaning
Active Valid license, updates available.
Inactive Key entered but not activated.
Inactive on this site The key is valid but this site is not one of its activations.
Expired The license period ended. The plugin keeps working.
Disabled, Revoked The license was turned off on wbcomdesigns.com. Contact support.
Invalid The key does not match a license.
Item mismatch The key belongs to a different product.
No activations left Every site on the license is in use. Deactivate one first.

Move a license to another site

  1. On the old site, open Settings > License and deactivate the key.
  2. Activate it on the new site.

What's new in 1.8.0

Version 1.8.0 adds the Hiring Pipeline page, guest job alerts, radius search, a fuller credit checkout and more. Install it with the matching version of WP Career Board (Free). For every past release, see the changelog in the plugin's readme.txt.

What you can do now

Open a job's pipeline from the employer dashboard

Each job row on the employer dashboard has a Pipeline button. It opens that job's Kanban board on the Hiring Pipeline page. Sites that upgrade get the page created for them. See Hiring Pipeline page.

  • A stage set to Hired or Rejected sets the application status. Moving a card out of such a stage sets the status back to Reviewing.
  • Withdrawn, position closed and job removed applications leave the board.

Let visitors save job alerts without an account

Visitors enter an email address and a search, then confirm by email. You choose whether guest alerts are on and how many alerts one person can keep, and you can see every saved alert, under Settings > Job Alerts. Alert emails carry an unsubscribe link. See Job alerts.

Search jobs by distance

Visitors pick a place and a radius in kilometres. Totals and paging stay correct. Coordinates are looked up in the background after a job is saved. See Job map.

Find candidates

The Find Candidates page has search and filters. The resume map block shows up to 500 pins of public resumes and says when there are more. See Find Candidates.

Sell credits with receipts, coupons and tax

Credit checkout supports numbered receipts, coupons, a tax rate and a paid Featured upgrade. Employers also get a credit refund email. See Checkout, receipts and emails.

Let members turn off optional emails

Signed-in members can switch off optional emails under Email Notifications in their dashboard account section. In Pro, the optional emails are the job alert digest, the low credit balance warning and the featured listing ended notice. Emails about accounts, applications and payments are always sent.

Get more from the notification bell

Admins are alerted when a job or a member is reported. Employers are told 3 days before a job ends.

Export and erase a member's data

Personal data export and erase now cover a member's resumes, saved job alerts, bell notifications and app devices.

Other changes

  • The installable app uses your Brand colour. See PWA.
  • Push notifications go to the native companion app.
  • Resume printing is fixed: no blank first page, the sidebar prints beside the main column, and a short resume fits one page. See Print and download a resume.
  • Field Builder: creating or editing a field no longer fails.
  • Bundled Wbcom Credits SDK 1.9.5.

Earlier releases

  • 1.7.x - Native Stripe and PayPal credit checkout, a pipeline stage manager on the Boards tab, native mobile push, an admin Transactions view with refunds, and resume privacy enforced wherever resumes are read.
  • 1.6.0 - Analytics dashboard, and a job map that narrows to the current job list results.
  • 1.5.0 and earlier - See the changelog in readme.txt.

For developers

Pro settings reference

Pro adds tabs to Career Board > Settings: Resumes, Job Alerts, Analytics, Boards, Field Builder, Credits, AI Settings, Job Feed, Integrations and License. This page lists the options on them, with the default a fresh install starts with.

Shared settings (jobs, applications, emails, Brand) live in the Free docs.

Resumes

Option Default What it does
Max resumes per candidate 2 How many resumes one candidate can keep. Allowed range 1 to 20.
Candidate directory visibility Public - anyone can browse Who can browse Find Candidates, on the page and through the API. Other choices: Logged-in members only, Approved employers only.
Single resume visibility Public - anyone can view Who can open one public resume. Same three choices.

If the Find Candidates page is not set, the tab shows Create Missing Resume Pages. See Resume builder setup.

Job Alerts

Option Default What it does
Guest alerts On Lets visitors without an account save an alert with an email address. They confirm by email first, and every alert email has an unsubscribe link.
Alerts per person 10 Most saved alerts one member or one email address can have. Range 1 to 100.

Below the options the tab lists saved alerts (subscriber, search, frequency, last sent, status). An alert shows "Waiting for email confirmation" until the guest confirms. See Job alerts.

Analytics

Read-only. Shows job views (30 days), applications per job, total applications, published jobs and top jobs by views. When credits are in use it also shows credits issued, spent and outstanding, revenue after refunds, and a button to export the credit ledger as CSV. Below that, a Transactions card lists every Stripe and PayPal purchase and refund, filtered by All, Purchases or Refunds, with a Receipt link and a Refund button on refundable purchases. Figures refresh every few minutes. See Analytics.

Boards

Lists boards with search and paging, lets you add, edit and delete boards, and manages each board's pipeline stages. When you edit a board, its Board Settings box has these options:

Option Default What it does
Credit Cost Per Job 0 Credits an employer pays to post on this board. 0 means posting is free.
Moderation Use global default Or Auto-publish, or Requires approval. Global default follows the site-wide Auto-publish jobs setting.
Listing length (days) 0 How long a job stays open when the employer sets no deadline. 0 follows the default listing length under Settings > Jobs.
Currency Site salary currency (USD if unset) Currency shown for jobs on this board.

See Multi-board and Configure pipeline stages.

Field Builder

The field builder app. It has no options of its own. See Field Builder overview.

Credits

The tab warns you when employers cannot buy credits (credits off, or no gateway and no mapped product) and when a board charges credits while nothing can sell them.

Option Default What it does
Low Balance Alert 5 At or below this balance the employer dashboard shows a "Low balance" banner and a reminder email is queued. 0 turns both off.
Featured upgrade 10 Credits to feature a job. 0 turns the paid upgrade off. See Featured upgrade.
Native checkout On Stripe and PayPal checkout without leaving the page.
Product mapping On Buying credits through a mapped WooCommerce, PMPro or MemberPress product.
Credit packs and pricing none Fixed packs and a per-credit rate for custom amounts. See Credit packages.

Checkout and receipts (defaults):

Option Default
Billing details Name, email and country (or Full postal address)
Tax rate (%) 0, added on top of the pack price
Tax label blank, shown as "Tax"
Business name blank, uses the site name
Business address, Your VAT / GST number blank
Receipt number prefix INV-

Coupons is a table of code, discount (Percent off or Amount off), amount, expiry date, usage limit and active. Fill a blank row to add a coupon, clear its code to delete it.

Other cards on the tab: Direct payment gateways (Stripe and PayPal credentials, see Stripe setup), Credit mappings (provider, product or plan, credits), Detected providers and Admin credit adjustment (see Manual adjustments and refunds). The Transactions list is on the Analytics tab.

AI Settings

Everything here is optional. See AI overview and AI providers.

Option Default What it does
Analysis and ranking Disabled Provider for application ranking, AI job descriptions and chat search. Claude, OpenAI or Ollama.
Matching (embeddings) Disabled Provider for candidate-to-job matching. OpenAI or Ollama. Claude has no embeddings.
OpenAI API key, Anthropic API key empty Saved keys are not shown again; leave blank to keep.
Ollama URL http://localhost:11434 Address of your Ollama server.
Claude model claude-sonnet-4-6 Haiku, Sonnet or Opus.
OpenAI model gpt-4o-mini Also gpt-4o. Embedding model default text-embedding-3-small (or 3-large).
Ollama models llama3 and nomic-embed-text Completion and embedding model names as installed.
Auto-score applicants on submit Off Scores each new application in the background. One model call per application.
Show an AI-use notice on the application form On for new installs, off for sites upgraded from before this option existed Tells applicants employers may use AI to review applications. The notice shows only while an analysis provider is set.

Index existing jobs runs once to index jobs created before AI was on. It needs an embedding provider.

Job Feed

Option Default What it does
Enable feed Off Publishes an XML feed at /wcb-jobs.xml.
Contact email Site admin email Shown in the email field of each job entry.

See Job feed.

Integrations

Option Default What it does
Profile tabs On My Jobs and My Career tabs on BuddyPress member profiles.
Application notifications On In-app BuddyPress notifications to employers for new applications.
Group job boards Off Each BuddyPress group gets its own board and a Jobs tab.
Map provider Leaflet / OpenStreetMap Or Google Maps (API key) or Mapbox (access token). Leaflet needs no key.
Google Maps API key, Mapbox access token empty Saved keys are not shown again.

The three BuddyPress options are greyed out until BuddyPress is active. See BuddyPress integration.

The PWA settings card has no option of its own. It links to Settings > Brand, whose colour the installable app uses. See PWA and Job map.

License

Shows product, status, expiry (or Lifetime), activations used, the license key field and a usage-data setting. The license gates updates and the mobile app connection only. Every web feature keeps working without it. See License activation.

Pages

Pro adds these pages to the shared page list: Hiring Pipeline, Job Map and Find Candidates. Assign or recreate them under Settings > Pages.

Application Pipeline

Kanban-style ATS pipeline with configurable hiring stages.

Application pipeline - overview

You can give employers a Kanban board for each job. Applicants show up as cards in hiring stages such as Screening and Interview, and employers drag a card to the next stage as they move through the process.

What you can do

  • Set stages per board. Each job board has its own stages, so an Engineering board and a Sales board can hire differently.
  • Move applicants by dragging. The Kanban board shows one column per stage. Each column loads 25 cards at a time and has a Load more button.
  • End a process with an outcome. A stage can carry the outcome Hired or Rejected. Moving a card there sets the application status to match.
  • Color the stages. Each stage has a color for its column.
  • Open one job's board from the employer dashboard. Each job row has a Pipeline button. See Hiring Pipeline page.

Default stages

A board with no stages gets a default set. The default stages are:

  1. Screening
  2. Interview
  3. Offer
  4. Hired (outcome: Hired)
  5. Rejected (outcome: Rejected)

You can rename, recolor, reorder or delete any of them. See Configuring pipeline stages.

Board and status stay in sync

A card's column and the application's status follow each other.

  • Moving a card into a Hired or Rejected stage sets that status. The candidate gets the normal status message once.
  • Moving a card out of a Hired or Rejected stage sets the status back to Reviewing.
  • If the status changes somewhere else, such as the applications list, the card moves to match. Hired and Rejected go to the stage with that outcome, if the board has one.
  • Withdrawn, Position closed and Job removed applications leave the board. You cannot move them, and the board shows a message if you try.
  • A card that was off the board, or in a Hired or Rejected stage, goes back to the first column when its application returns to a working status.

Where to next

Configuring pipeline stages

You can decide which hiring stages each board uses. Stages belong to a job board. A job uses the stages of the board it was posted to, or of the default board when it has no board.

Open the stage manager

  1. Go to Career Board → Settings → Boards.
  2. Find the board. The Stages column shows its stage count and a Manage button.
  3. Click Manage. The Pipeline stages panel opens.

What you can do in the panel

  • Add a stage. Type a name in New stage name..., pick a color and click Add Stage. The stage goes to the end.
  • Rename a stage. Edit the name in its row.
  • Change a color. Use the color picker in its row.
  • Reorder stages. Use the up and down arrows. The Kanban board shows columns in this order.
  • Delete a stage. Click Delete on the row and confirm.

Every change saves at once. Click Close when you are done.

When you delete a stage that holds cards, the cards move to the first remaining column of that board.

Outcome stages

A stage can carry the outcome Hired or Rejected. When a card moves into such a stage, the application status becomes that outcome, the change is logged and the candidate gets the usual status message. Moving the card back out sets the status to Reviewing.

The default Hired and Rejected stages carry these outcomes. A stage you add in the panel has no outcome. If you delete the default Hired or Rejected stage, that board has no stage for that outcome, and an application marked Hired or Rejected elsewhere does not move to a stage.

Use the board

Employers drag a card to another column to move it. If the move fails, the card returns to its column and a message shows. Withdrawn, position closed and job removed applications cannot be moved.

Who can do what

  • See a job's board: the job's owner, or a user with the wcb/moderate-jobs or wcb/manage-settings ability. All of them also need wcb/view-applications.
  • Move a card: the job's owner, or a user with wcb/moderate-jobs. They also need wcb/view-applications.
  • Anyone else sees "You don't have access to this job's pipeline." with a link back to the dashboard.

REST API for stages

Action Route Who
List a board's stages GET /wcb/v1/boards/{id}/stages The board's author, or wcb/manage-boards
Create a stage POST /wcb/v1/boards/{id}/stages wcb/manage-boards
Update a stage PUT /wcb/v1/boards/{id}/stages/{stage_id} wcb/manage-boards
Delete a stage DELETE /wcb/v1/boards/{id}/stages/{stage_id} wcb/manage-boards
Read a job's board GET /wcb/v1/jobs/{id}/kanban As in "Who can do what"
Move a card PATCH /wcb/v1/applications/{id}/stage with stage_id As in "Who can do what"

Create accepts label, color, sort_order, is_terminal and terminal_outcome (hired or rejected). Update accepts label, color and sort_order.

Extend the board

  • wcbp_default_pipeline_stages - change the stages a new board starts with.
  • wcbp_pipeline_board_for_job - choose which board's stages a job uses.
  • wcbp_kanban_stage_limit - cards per column per page. Default 25.
  • wcbp_kanban_card_columns - change the columns and cards shown for a job.
  • wcbp_application_stage_changed - fires when someone moves a card.
  • wcbp_application_stage_assigned - fires when the plugin puts an application in a stage.

Hiring Pipeline page

Employers can open the Kanban board for any of their jobs from one page. The Hiring Pipeline page shows the board for the job in the address, for example /hiring-pipeline/?job=123.

Open a job's board

On the employer dashboard, each job row has a Pipeline button. It opens the Hiring Pipeline page for that job. The button shows only when the page exists.

With a job open, the page shows a Back to dashboard link and the heading "Hiring Pipeline: job title". The title shows only to people who may see that job's board.

Opened with no ?job=, the page tells you to use the Pipeline button on your employer dashboard and links to the dashboard.

The page

  • The setup wizard creates the page, with the slug hiring-pipeline.
  • On sites upgraded to 1.8.0, the page is created automatically.
  • It is listed under Career Board → Settings → Pages as Hiring Pipeline Page. If it is missing, click Create Missing Pages there.

The page holds the Kanban block. You can also place a board on a page of your own with the shortcode [wcbp_application_kanban jobId="123"].

Access

Someone who may not see the job's board gets "You don't have access to this job's pipeline." and a link back to the dashboard. Refreshing does not change this. See Configuring pipeline stages for who has access.

Resume Builder

Structured resume builder, single-page form, and resume search.

Resume Builder - Overview

Candidates can build structured resumes on your site, attach one to a job application, and choose whether employers can find it. You decide who can browse the candidate directory.

What candidates can add

A resume is made of sections. Each section holds entries.

Section Fields
Professional Summary A free-text overview
Work Experience Job title, company, employment type, location, start and end date, "Currently Working Here", description, skills used
School School name, certificate, field of study, start and end date, grade, description
College / University Institution, degree type, field of study, start and end date, GPA, description, achievements
Skills Skill and proficiency level (Beginner, Intermediate, Advanced, Expert)
Languages Language and proficiency level (Basic, Conversational, Fluent, Native)
Certifications Certificate name, issuing body, issue and expiry date, credential ID and URL
Portfolio & Links Label (for example "GitHub") and URL

The builder also has two profile fields that feed the candidate directory filters: Years of experience and Open to new opportunities.

Candidates open and close each section, and add, edit or remove entries in it.

Attach a resume to an application

When a candidate applies for a job, they can pick one of their saved resumes. The employer sees the resume you built here, not only an uploaded file.

Multiple resumes

Candidates can keep more than one resume, for example one for software roles and one for design roles. My Resumes on the candidate dashboard lists each resume with its date.

You set the limit under Career Board → Settings → Resumes → Max Resumes Per Candidate. The default is 2 and you can set 1 to 20. When a limit applies, the dashboard shows a count such as "2 of 2 resumes".

Who can see a resume

Every resume has a Public switch in the builder header. It is off by default.

  • Off (Private): only the candidate and employers they apply to can see the resume.
  • On (Public): the resume has its own page at /resume/{slug}/ and appears in the candidate directory (the Find Candidates page).

You control the audience under Career Board → Settings → Resumes:

  • Candidate directory visibility - "Public - anyone can browse", "Logged-in members only" or "Approved employers only". You tick approved employers on their user profile.
  • Single resume visibility - "Public - anyone can view", "Logged-in members only" or "Approved employers only".

A resume appears in the directory only when the candidate has turned on Public and your setting allows the visitor to browse.

Members who have blocked each other do not see each other's resumes in the candidate directory.

Next steps

Set up the Resume Builder

You can give candidates a resume builder and a public candidate directory. Most sites need no manual page work, because the candidate dashboard already opens the builder for you.

Candidates use the dashboard

On the candidate dashboard, My Resumes lists each resume with View, Edit and Delete. Edit opens the Resume Builder inside the dashboard. You do not need a separate builder page.

Create the Find Candidates page

The setup wizard creates a Find Candidates page at /find-candidates/. It holds the Resume Search Hero and Find Resumes blocks. A page created earlier at /find-resumes/ keeps working.

To check or change the page:

  1. Go to Career Board → Settings → Pages.
  2. Find Find Candidates Page. It is the page that holds the Find Resumes block.
  3. Select the page and click Save Changes.

If the page is missing, click Create Missing Pages on the Pages tab. The Resumes tab shows Create Missing Resume Pages when the page is not set.

There is no page setting for the builder itself.

Choose who can browse and how many resumes

Go to Career Board → Settings → Resumes:

  • Max Resumes Per Candidate - 1 to 20, default 2.
  • Candidate directory visibility - who can browse the directory.
  • Single resume visibility - who can open a resume page.

Click Save Resume Settings. See Resume Builder overview for what each choice means.

Put the builder on your own page

You can also place the builder on a page of your own.

  1. Go to Pages → Add New.
  2. Add a Shortcode block with [wcbp_resume_builder].
  3. Publish the page.

The builder loads the resume named in the ?resume_id= address parameter. If the address has no valid resume_id for the signed-in candidate, it opens their most recently edited resume. The block has no settings in the editor.

To add fields to the builder, see Custom resume fields.

Resume Builder - Candidate guide

You can build a resume, keep several versions, and choose whether employers can find it.

Open the builder

  1. Sign in and open your Candidate Dashboard.
  2. Click My Resumes.
  3. Click + New Resume, type a title (for example "Software Engineer Resume") and click Create. Or click Edit on a resume you already have.

The builder opens with that resume loaded. If the site sets a limit on resumes, the page shows how many you have used, such as "1 of 2 resumes".

Build your resume

The builder is a list of sections. Click a section header to open or close it.

Summary and profile

  • Professional Summary - a short overview of your background and goals.
  • Years of experience - used by the Experience filter in the candidate directory.
  • Open to new opportunities - when on, you appear under Open to Work in the directory.

Add an entry

  1. Open a section, for example Work Experience.
  2. Click Add Entry. A blank entry opens for editing.
  3. Fill in the fields.
  4. Click Done. The entry collapses to a compact row.

Click the pencil on a row to edit it again.

What each section asks for

Work Experience: Job Title, Company, Employment Type, Location, Start Date, End Date, Currently Working Here, Description, Skills Used.

School: School Name, Certificate / Qualification, Field of Study, Start Date, End Date, Grade, Description.

College / University: Institution, Degree Type, Field of Study, Start Date, End Date, GPA, Description, Achievements.

Skills: Skill and Proficiency Level (Beginner, Intermediate, Advanced or Expert).

Languages: Language and Proficiency Level (Basic, Conversational, Fluent or Native).

Certifications: Certificate Name, Issuing Body, Issue Date, Expiry Date, Credential ID, Credential URL.

Portfolio & Links: Label (for example "GitHub") and URL.

Remove an entry

Click Remove in the entry, or the bin icon on its row. Confirm the prompt. Then click Save Resume so the removal is saved.

Save your resume

  • Click Save Resume in the builder header at any time. The button reads Saving... while it works.
  • Clicking Done on an entry, changing Years of experience or switching Open to new opportunities also saves after a few seconds.
  • Click Save Resume after you add or remove an entry or change the summary.

Delete a resume

  1. Open My Resumes on your dashboard.
  2. Click Delete on the resume.
  3. Click Confirm.

A deleted resume is removed permanently.

Choose who can see it

The Public switch in the builder header is off by default.

  • Off: only you and the employers you apply to can see the resume.
  • On: your resume has its own page at /resume/{slug}/ and appears in the site's Find Candidates directory.

The switch takes effect straight away. The site owner can also limit the directory to signed-in members or approved employers. A resume you keep private never appears in the directory.

Quick Resume Form

You can let candidates fill in a short profile in one screen: headline, summary, skills, location and a photo. Use it where a full resume is too much, such as onboarding, a sidebar or a modal.

What it collects

  • Profile photo (optional)
  • Headline - required, for example "Senior Backend Engineer - 8 years - open to remote"
  • Professional summary
  • Top skills - comma-separated, for example "PHP, Laravel, MySQL". The candidate directory Skills filter uses them.
  • Years of experience
  • Location - free text
  • Open to new opportunities - when on, the candidate appears under Open to Work in the member directory filters

The button reads Save profile. A "Profile saved" message shows for a few seconds and the form keeps the values so the candidate can keep editing.

Which resume it edits

The form edits the signed-in candidate's existing resume and creates one on the first save. It does not read ?resume_id=. If the candidate has several resumes, use the Resume Builder to edit a specific one.

A resume created by this form starts as Public, so it can appear in the candidate directory straight away. After that, the form does not change the Public switch. The candidate changes it in the Resume Builder. The site's directory visibility setting still applies.

Add it to a page

Block

Insert Resume Form (Quick Profile) from the block inserter, in the Widgets category. The block sidebar has two options:

  • showPhotoField - set to off to hide the photo upload. Default on.
  • compact - a denser layout for narrow columns. Default off.

Shortcode

[wcbp_resume_form_simple]
[wcbp_resume_form_simple compact="true" showPhotoField="false"]

Signed-out visitors see "Please log in to complete your profile."

Add your own fields

The wcb_resume_form_fields filter adds fields to this form, the Resume Builder and the single-page form at once. It receives the field groups (an empty array by default) and the resume post ID, and returns the groups.

add_filter( 'wcb_resume_form_fields', function ( $groups, $resume_id ) {
    $groups[] = array(
        'id'     => 'preferences',
        'label'  => __( 'Work preferences', 'my-theme' ),
        'fields' => array(
            array(
                'key'     => '_wcb_preferred_timezone',
                'label'   => __( 'Preferred timezone', 'my-theme' ),
                'type'    => 'select',
                'options' => array(
                    'utc' => 'UTC',
                    'est' => 'EST',
                    'pst' => 'PST',
                    'ist' => 'IST',
                ),
            ),
        ),
    );
    return $groups;
}, 10, 2 );

Each group has id, label and fields. Each field has key, label and type (text, textarea, email, tel, url, number, date, select, checkbox, radio or multiselect), plus optional required, placeholder, description and options (a value-to-label map). See Custom resume fields.

Custom resume fields

You can add your own fields to resumes, for example a GitHub link or a preferred timezone. You declare a field once and it appears in the Resume Builder, the single-page resume form and the Quick Resume Form. If you prefer no code, use the Field Builder.

Add fields with code

The wcb_resume_form_fields filter receives the field groups (an empty array by default) and the resume post ID, and returns the groups. Each group has id, label and fields. Each field has key, label and type, plus optional required, placeholder, description and options.

add_filter( 'wcb_resume_form_fields', function( $groups, $resume_id ) {
    $groups[] = [
        'id'     => 'links',
        'label'  => __( 'Online presence', 'my-plugin' ),
        'fields' => [
            [
                'key'      => '_wcb_resume_github_url',
                'label'    => __( 'GitHub profile', 'my-plugin' ),
                'type'     => 'url',
                'required' => false,
            ],
            [
                'key'      => '_wcb_resume_website_url',
                'label'    => __( 'Personal website', 'my-plugin' ),
                'type'     => 'url',
                'required' => false,
            ],
        ],
    ];
    return $groups;
}, 10, 2 );

After you add this:

  • The Resume Builder, the single-page form and the Quick Resume Form show the "Online presence" group.
  • Each value is saved as post meta on the resume under the key you declared. The key is lowercased when saved, and nothing is added in front of it, so pick a unique key.
  • Only keys you declare in the filter are saved. Other submitted keys are ignored.
  • You read a value with get_post_meta( $resume_id, '_wcb_resume_github_url', true ).

Field types

text, textarea, email, tel, url, number, date, select, checkbox, radio, multiselect.

How values are cleaned before saving

  • email - cleaned as an email address.
  • url - cleaned as a URL.
  • number - saved as a number, or empty if the value is not numeric.
  • date - saved only in YYYY-MM-DD form, otherwise empty.
  • textarea - cleaned as multi-line text.
  • checkbox - saved as 1 when on and empty when off.
  • select and radio - saved only if the value is one of the field's options, otherwise empty.
  • multiselect - saved as a comma-separated list of the chosen option values.
  • Everything else - cleaned as single-line text.

To reject or change a value, use the wcb_save_custom_field filter. It receives the cleaned value, the field key and the resume ID. Return null to skip saving, or a scalar to replace the value.

Pre-fill the Resume Builder

The wcb_resume_form_initial_state filter changes what the Resume Builder starts with. It receives the state array and the resume post ID. Custom field values sit under the customFields key of the state, keyed by field key.

add_filter( 'wcb_resume_form_initial_state', function( $state, $resume_id ) {
    $author_id = (int) get_post_field( 'post_author', $resume_id );
    $links     = get_user_meta( $author_id, '_partner_profile_links', true );
    if ( $links ) {
        $state['customFields']['_wcb_resume_github_url'] = $links['github'] ?? '';
    }
    return $state;
}, 10, 2 );

This filter applies to the Resume Builder only.

Save and read over the REST API

  • Save: PUT /wcb/v1/resumes/{id} with a custom_fields object in the body, keyed by field key.
  • Read: GET /wcb/v1/resumes/{id} does not return custom fields by default. Add them with the wcb_rest_prepare_resume filter. It receives the response data, the resume post, the request and a context string.

See also

Single-page resume form

You can choose how candidates edit a resume. Pro has three forms. All three save to the same resume, so a candidate can switch between them without losing data.

The three forms

Form Block Shortcode Best for
Resume Builder wcb/resume-builder [wcbp_resume_builder] Candidates building a resume section by section. Sections open and close and entries show as compact rows.
Resume Form (Single-Page) wcb/resume-form [wcbp_resume_form] Candidates who want every section visible on one scrolling page.
Resume Form (Quick Profile) wcb/resume-form-simple [wcbp_resume_form_simple] A short profile in a sidebar, modal or onboarding step. See Quick Resume Form.

The Resume Builder and the single-page form edit the resume in the ?resume_id= address parameter. If the address has no resume of the candidate's own, they open the candidate's most recently edited resume. The Quick Profile form edits the candidate's existing resume, or creates one on the first save.

What the single-page form shows

  • A Public switch. Off means only the candidate and employers they apply to can see the resume. On lists it in the candidate directory.
  • Professional Summary, Years of experience and Open to new opportunities.
  • One block for each section: School, College / University, Work Experience, Certifications, Skills, Languages and Portfolio & Links. Each has an Add button, for example Add Work Experience, and each entry has a Remove button that asks for confirmation.
  • Additional details for any custom fields you add.
  • A Save Resume button. A "Saved" message shows when it finishes.

Switch a page to the single-page form

  1. Go to Pages → All Pages and open the page that holds the Resume Builder block.
  2. Remove the Resume Builder block.
  3. Add the Resume Form (Single-Page) block, or the shortcode [wcbp_resume_form].
  4. Update the page.

Candidates keep their existing data.

The candidate dashboard opens its own built-in Resume Builder when a candidate clicks Edit. It does not use the block you place on another page.

Block options

Resume Form (Single-Page) has one option, compact, for tighter spacing in narrow columns. It is off by default.

Change the sections

These filters change the sections of both the Resume Builder and the single-page form:

  • wcbp_resume_groups - add, remove or rename sections and their fields.
  • wcbp_resume_textarea_fields, wcbp_resume_checkbox_fields and wcbp_resume_date_fields - change a field's input type.

The Quick Profile form has no repeating sections, so these filters do not apply to it. Use the wcb_resume_form_fields filter to add a field to all three forms.

Next steps

Find Candidates and the resume map

You can give employers a page to search and filter candidate resumes. The Find Candidates page lists resumes that candidates have made public, to visitors your settings allow.

The page

The setup wizard creates the page at /find-candidates/. It holds the Resume Search Hero block (wcb/resume-search-hero) and the Find Resumes block (wcb/resume-archive). Sites that made the page earlier at /find-resumes/ keep working.

Map the page under Career Board → Settings → Pages (Find Candidates Page). If it is missing, click Create Missing Pages on the same tab.

Who can browse

Set the audience with Candidate directory visibility under Career Board → Settings → Resumes: everyone, logged-in members only, or approved employers only. A resume appears only when the candidate has turned on its Public toggle. See Resume Builder overview.

Search and filters

Control What it does
Search Every word must appear in the resume title, headline, summary, location or a skill. Up to 6 words of 2 or more letters.
Skills Filters by skill. Shows the 30 most used skills.
Experience Filters by experience level: Entry level (0-2 years), Mid level (3-5), Senior (6-10) or Lead / Principal (11 or more), from the candidate's Years of experience.
Location Matches part of the resume's location text.
Open to Work Shows only candidates marked open to work.
Sort Newest first or Oldest first.

The same filters work on GET /wcb/v1/resumes with search, skill, experience, location, open_to_work, order (ASC or DESC), page and per_page (up to 50, default 12). The route follows the same audience setting as the page.

The resume map

You can show candidates on a map with the Resume Map block (wcb/resume-map, shortcode [wcbp_resume_map]). It pins public resumes that have a location and follows the same audience setting as the directory. A candidate's location comes from the Location field of the Quick Resume Form.

  • It holds the newest 500 pins. When there are more candidates, a note under the map says "Showing the newest 500 of N candidates. Use the candidate search to find the rest."
  • Visitors can search by city or postcode, pick a radius (5, 10, 25, 50 or 100 km; the default is 25 km) and use Use my location.
  • If no one is in the area, the map says "No candidates found in that area. Try a wider search radius."
  • A resume is placed on the map shortly after the candidate saves a location. The place lookup runs in the background, not while saving. See Job Map for map providers.

The block has one setting, Height, default 480 px.

Job Alerts

Keyword and location alerts for candidates.

Job alerts

You can let members and visitors save a job search and get an email when new jobs match it.

How people create alerts

  • Alert me button. It is on the job listings toolbar and saves the current search words and filters. Members are subscribed at once. Visitors type their email first.
  • Job Alerts block (wcb/job-alerts, shortcode [wcbp_job_alerts]). It shows only to signed-in members. Members pick Instant, Daily or Weekly and click Subscribe. The block saves the current search words and the category, job type, location, salary and remote filters. It also lists Active Alerts, where members can delete an alert.

The default frequency is Daily.

Guest alerts

Visitors without an account can save an alert with their email address.

  1. The visitor types an email and clicks Alert me.
  2. The button changes to "Check your email to confirm".
  3. The visitor gets the email "Confirm your job alert" and clicks the link.
  4. Nothing is sent until the link is clicked.

Every alert email has an unsubscribe link that works without signing in. The emails also carry one-click unsubscribe headers.

After 5 alert requests from one IP address, further requests are refused for an hour.

Manage alerts as a member

On the candidate dashboard, open Job Alerts. A member can change an alert's frequency or delete it there.

Settings

Go to Career Board → Settings → Job Alerts.

Setting Default What it does
Guest alerts On Lets visitors without an account save an alert with their email. Turn it off to show the Alert me button to members only.
Alerts per person 10 The most alerts one member or one email address can keep (1 to 100).

The same tab lists the saved alerts, 50 per page. It shows the subscriber (the email for guests), the search, the frequency, when the alert was last sent and its status. A guest alert shows "Waiting for email confirmation" until it is confirmed.

What gets matched

An alert matches a job when the job meets every criterion set on the alert. Empty criteria are ignored.

  • Keyword - every word must appear in the job title, description or company name.
  • Category, Job type, Location, Experience, Tag - the job must have one of the alert's terms.
  • Board - the job must be on the alert's board. An alert with no board matches all boards.
  • Company - the job must belong to that company.
  • Salary minimum - a job whose top salary is below it does not match.
  • Salary maximum - a job whose bottom salary is above it does not match.
  • Remote - only jobs marked remote.

A job with no salary set is not excluded by the salary criteria. Only confirmed alerts are sent.

When emails go out

Frequency When
Instant When a job becomes public: approved, published automatically or scheduled. Each job is sent once, so reopening or re-approving it does not send it again.
Daily Once a day at 8:00 (UTC)
Weekly Mondays at 8:00 (UTC)

Daily and weekly emails list only the jobs published since the alert was last sent. Imported jobs do not send alerts unless you return true from the wcbp_alerts_notify_on_import filter.

Daily and weekly emails run on WP-Cron. On a low-traffic site, set up a real server cron that runs wp cron event run --due-now so they go out on time.

Emails

Set the sender name and address under Career Board → Settings → Emails. The alert emails are listed there as Job Alert Digest and Confirm Job Alert (guest), so you can edit their subject and text. Use an SMTP plugin for reliable delivery.

Email is the built-in channel. Add-ons can add channels, such as Slack or SMS, with the wcbp_alert_dispatch_channels filter. The email channel fires wcbp_send_alert_email.

REST API

Action Route Who
List your alerts GET /wcb/v1/alerts Signed-in member
Create an alert POST /wcb/v1/alerts Member, or a visitor with an email when guest alerts are on
Update an alert PUT /wcb/v1/alerts/{id} Alert owner, or wcb/manage-settings
Delete an alert DELETE /wcb/v1/alerts/{id} Alert owner, or wcb/manage-settings
Unsubscribe GET or POST /wcb/v1/alerts/{id}/unsubscribe/{token} Anyone with the signed link

Update changes the frequency, search words, filters and board. Creating a guest alert returns needsConfirm: true.

Privacy

Job alerts are part of WordPress Export Personal Data and Erase Personal Data requests. This covers alerts a member created while signed in and alerts a guest subscribed to with an email address.

Field Builder

Add custom fields to jobs, candidates, and applications.

Custom Field Builder - overview

You can add your own fields to jobs, company profiles, candidate profiles, resumes and job applications, without code. For example, add "Remote policy" to every job, or a screening question that every applicant must answer.

What you can do

  • Add fields to job listings (Remote policy, Visa sponsorship, Tech stack).
  • Add fields to company profiles (Funding stage, Glassdoor rating).
  • Add fields to candidate profiles (Notice period, Portfolio URL).
  • Add fields to resumes (Availability, Certifications).
  • Add application questions that applicants answer when they apply.
  • Group fields into sections with a heading.
  • Mark fields required, and choose who can see them on the job page.
  • Show job fields on the job page, offer them as filters on the job listing, and send some of them to Google for Jobs.

Open the Field Builder at Career Board > Settings > Field Builder.

Fields apply to every board

Each field group is defined once and applies to every board. There is no board selector in the Field Builder.

For Job fields and Application questions, each group has a Hide on boards control. A group shows on every board by default. Add a board to the control to hide that group on that board. Company, candidate and resume fields have no per-board control.

Where the answers show up

  • Forms - the fields appear on the matching form: the job form for job fields, the company profile in the employer dashboard for company fields, the candidate dashboard for candidate fields, the Resume Form (Quick Profile) block for resume fields, and the apply form for application questions. Required application questions block the application until they are answered.
  • Job page - answered job fields show under the description in an Additional details section.
  • Job listing filters - a Dropdown, Radio, Multi-select or Checkbox job field with Filterable on shows as a filter group in the job listing sidebar. Only Public fields can be filters. The filter uses the meta_<field key> query parameter.
  • Google for Jobs - pick a Google for Jobs property when you add a job field, and its value is sent in the job's structured data. See Creating custom fields.
  • Job REST response - custom job field values are included in the job's custom_fields.

Who sees a job field

This applies to the job page and the job REST response.

Setting Who sees it
Public Everyone, including guests. The default.
Employer only The job's author and site staff.
Admin only Site staff only.

For developers

Field groups reach each form through these filters: wcb_job_form_fields, wcb_company_form_fields, wcb_candidate_form_fields, wcb_resume_form_fields and wcb_application_form_fields_groups.

Add-ons can listen to wcbp_field_group_saved, wcbp_field_group_deleted, wcbp_field_definition_saved, wcbp_field_definition_deleted and wcbp_field_value_saved.

Field definitions are cached for 5 minutes, and the cache clears when you save or delete a group or field.

Where to next

Creating custom fields

You can create field groups and fields for jobs, companies, candidates, resumes and applications, and choose where each one shows.

Open the Field Builder

Go to Career Board > Settings and open the Field Builder tab.

The tabs are Job fields, Company fields, Candidate fields, Resume fields and Application questions. The note "These fields are global - they apply across all boards" shows on the tabs that have no per-board control.

Create a group

  1. Choose a tab.
  2. Click Add group.
  3. Enter a Group label, for example "Compensation".
  4. Click Create group.

Use Rename to change the label and Delete group to remove the group and its fields.

Hide a group on some boards

On the Job fields and Application questions tabs, open a group and use Hide on boards. Add the boards where the group should not show. The group shows on every other board.

Add a field

  1. Open the group.
  2. Click Add field.
  3. Fill in the form:
Setting What it does
Label The name shown on the form and the job page.
Field type One of 17 types. See Field types reference.
Visibility Public, Employer only or Admin only.
Required Marks the field as required. Application questions block the application until answered.
Google for Jobs property Job fields only, when adding. Sends the value to Google.
Filterable Job fields of type Dropdown, Radio, Multi-select or Checkbox. Adds a filter to the job listing (public fields only).
Choices For Dropdown, Multi-select, Radio and Checkbox types. Add at least one choice.
  1. Click Add field.

The field key is created for you and never changes, so stored values stay linked when you rename the field. It starts with wcbf_, followed by the Google property name if you picked one, or a generated ID.

Google for Jobs property

When you add a job field, pick one of these properties to send its value in the job's structured data:

Field Google property
Benefits jobBenefits
Qualifications qualifications
Responsibilities responsibilities
Skills skills
Education educationRequirements
Experience experienceRequirements
Industry industry
Work hours workHours

One field can feed each property. If another field already does, saving shows "Another field already feeds this Google property. Choose a different one, or none." The property is fixed after the field is created. Only public fields are sent to Google. A checkbox field is not sent.

Application questions

Fields on the Application questions tab appear on the apply form of every job on a board that does not hide the group. Applicants answer them when they apply, and required questions must be answered.

Edit, reorder and delete

  • Edit changes the label, type, visibility, required state, choices and Filterable. The field key never changes.
  • Move up and Move down reorder fields inside a group.
  • Delete removes the field definition. Values already saved on jobs and applications are not removed.

Where fields appear

  • Job fields - the job form, the job page ("Additional details"), the listing filters and the job REST response.
  • Company fields - the company profile in the employer dashboard.
  • Candidate fields - the candidate dashboard profile.
  • Resume fields - the Resume Form (Quick Profile) block.
  • Application questions - the apply form.

REST API

The admin screen uses these routes. All require the wcb/manage-boards ability.

Method Route Purpose
GET /wcb/v1/fields/groups List groups (board_id, entity_type)
POST /wcb/v1/fields/groups Create a group
PUT /wcb/v1/fields/groups/{id} Update a group
DELETE /wcb/v1/fields/groups/{id} Delete a group
GET /wcb/v1/fields/groups/{group_id}/fields List a group's fields
POST /wcb/v1/fields/groups/{group_id}/fields Add a field. A duplicate field_key returns 409.
PUT /wcb/v1/fields/{id} Update a field
DELETE /wcb/v1/fields/{id} Delete a field
POST /wcb/v1/fields/reorder Reorder fields

Groups are stored under board 0, so pass board_id=0.

Field types reference

You can pick from 17 field types when you add or edit a field. Pick the type from the Field type dropdown. This page shows what each type looks like on the form, using the names shown in the dropdown.

Text

A single-line text box. Use it for short values such as a tech stack keyword, a notice period or a LinkedIn handle.

Long text

A multi-line text box, four rows high. Use it for longer answers such as a benefits overview or a company culture note.

Number

A number box. Use it for team size or years of experience required.

Email

An email box. Use it for a recruiter contact or an HR address.

URL

A web address box. Use it for a portfolio, GitHub or external application link.

Date

A date picker. Use it for an application deadline or an estimated start date.

Date range

Two date pickers labelled From and To. Use it for a contract period or a project duration.

Dropdown

A single-choice dropdown with a "Select..." first entry. You enter the choices when you add the field. Use it for remote policy (On-site, Hybrid, Remote) or seniority.

Multi-select

A group of tick boxes, one per choice, where people can tick more than one. Use it for tech stack or required certifications.

Checkbox

A single tick box with the field label next to it. Use it for a yes or no such as "Visa sponsorship available".

If you add choices to a Checkbox field, it becomes a group of tick boxes, like Multi-select.

Radio

A group of radio buttons, where only one can be chosen and all choices are visible. Use it for a preference question where a dropdown would hide the options.

File upload

A web address box with the hint "Paste a link to your file." It does not upload a file. People paste a link to a file they have already hosted.

Video URL

A web address box. Use it for a company culture video or a candidate introduction video.

Location

A single-line text box. Use it for a place name.

Salary range

Two number boxes labelled Min and Max.

Repeater group

A multi-line text box with the hint "Enter one entry per line." Each line is saved as a separate entry.

Conditional

A single-line text box. It does not show or hide based on another field.

Choices

Dropdown, Multi-select, Radio and Checkbox fields use choices. Enter them under Choices when you add or edit the field. You must add at least one choice for these types. Answers that are not one of the choices are ignored.

Filterable fields

Only Dropdown, Radio, Multi-select and Checkbox job fields can be made Filterable. See Creating custom fields.

Tips for choosing a type

  • Use Dropdown when the options are mutually exclusive and the list is short.
  • Use Radio when you want all the options visible at once.
  • Use Multi-select when more than one answer is valid.
  • Use Text for anything that does not fit another type.
  • Keep required fields to a minimum. Every required field makes forms harder to finish.

Job Map

Interactive map view of job listings by location.

Job Map

You can show your jobs on a map, so visitors can see where jobs are and search near a place. Add the Job Map block (wcb/job-map) to a page, or use the shortcode [wcbp_job_map].

The page

The setup wizard creates a Job Map page at /job-map/ that holds the block. It is listed under Career Board → Settings → Pages as Job Map Page. If it is missing, click Create Missing Pages on that tab. You can also add the block to any page.

What visitors can do

  • Click a pin to see the job title, company and location, with a View Job link.
  • Type a city or postcode, pick a radius and click Search. The map moves to that place and shows jobs within the radius, up to 100. The radius choices are 5, 10, 25, 50 and 100 km. The default is 25 km.
  • Click the Use my location button to search around their position.
  • If the place cannot be found, a line under the toolbar says "Location search failed. Please try again."

The map holds the newest 500 published jobs that have coordinates. When more jobs have a location, a line under the map reads "Showing the newest 500 of N jobs. Use the job search to find the rest." A job with no coordinates is left off.

If the map has no pins when the page loads, the block shows "No jobs with locations yet" and hides the search bar.

If a Job Listings block is on the same page, the map narrows its pins to the jobs in the current list.

Block setting

Setting Default What it does
Height 480 Height of the map in pixels.

Radius search in the REST API

You can search by distance on the jobs route: GET /wcb/v1/jobs?lat=48.85&lng=2.35&radius=25. radius is in kilometres, from 1 to 500, and defaults to 25. Only jobs with saved coordinates match.

The search area is a square around the point, so its corners reach a little past the radius (about 1.4 times).

Choose a map provider

Go to Career Board → Settings → Integrations → Map settings, choose a Map Provider and click Save Integrations.

Provider Key needed Notes
Leaflet / OpenStreetMap No The default. Turns places into coordinates with Nominatim.
Google Maps Yes Needs a Google Maps API key with the Geocoding API on.
Mapbox Yes Needs a Mapbox access token.

The provider only changes how places become coordinates. The map itself is always drawn with Leaflet and OpenStreetMap tiles. Once a key is saved, its field shows "Saved - leave blank to keep".

How jobs get coordinates

Coordinates are never looked up while you save. When a job or resume is saved, created or imported with a location, a background task looks up its coordinates shortly after.

  • The location comes from the job's Location terms. Terms such as "Remote", "Anywhere", "Worldwide", "Hybrid", "Other", "Work from home" and "WFH" are ignored, so a job with only those has no pin. The wcbp_non_geographic_location_terms filter changes this list.
  • A job is looked up again only when its location changes.
  • After an upgrade from a version before 1.7.1, existing jobs and resumes without coordinates are looked up in the background, 25 at a time with about a second between lookups.

Place search limits

The place search box calls GET /wcb/v1/geocode?address=.... The address must be 2 to 200 characters. Results are cached for 24 hours, and a failed lookup is cached for an hour. Each IP address can make 30 new lookups per hour; searches answered from the cache do not count. The count resets after an hour with no new lookup.

Filters

Filter Default What it does
wcbp_geocode_backfill_batch 25 Rows looked up in each background run (1 to 100).
wcbp_geocode_throttle_us 1100000 Pause between background lookups, in microseconds.
wcbp_geocode_rate_limit 30 New place searches per IP address per hour. 0 turns the limit off.

For the resume version of this map, see Find Candidates and the resume map.

Credit System

WooCommerce, PMPro, MemberPress, and Stripe credit packages for employers.

Credit system - overview

You can charge employers credits to post jobs and to feature them. You sell credits through Stripe, PayPal, WooCommerce, Paid Memberships Pro or MemberPress, and employers buy and track them from their dashboard.

How it works

  1. Set prices. Give a board a credit cost in Settings -> Boards (edit the board, Credit Cost Per Job). Posting stays free until you do. Set the price of the Featured upgrade under Settings -> Credits.
  2. Choose how credits are sold. Turn on Stripe or PayPal and add credit packs, or map a WooCommerce product, PMPro level or MemberPress membership to a credit amount.
  3. Employers buy credits. They open the Credits tab of their dashboard, pick a pack and pay. See Native Buy Credits checkout.
  4. Credits are held when a job is submitted to a paid board. If the balance is too short, nothing is created and the employer is sent to buy credits.
  5. Credits are spent when the job goes live. Approval, auto-publish and a moderator publishing from any screen all settle the hold.
  6. Credits come back if the job does not go live. A rejected, trashed or deleted job releases its hold, and the employer gets a credit refund email.

A job is charged once, whichever path moves it. Other cases:

  • A moderator publishes a job whose employer cannot pay: the job stays pending and goes live once the employer's balance covers it (oldest first).
  • The employer resubmits a rejected job: the hold is taken again.
  • The employer moves the job to a board with a different price: only the difference is charged or returned.
  • An expired or closed job is brought back: it is charged as a new listing period at the board price. Developers can change this with the wcb_job_republish_credit_cost filter.

Setup checklist

Employers can buy credits only when at least one selling route works:

  • Stripe or PayPal is enabled with valid keys and you have added at least one credit pack (or a custom-amount rate), or
  • a product, plan or membership is mapped under Credit mappings and its plugin is active.

If none works, the Credits settings tab shows "Employers can't buy credits yet", Career Board admin screens show "Employers can't buy credits, but a board charges them" while any board charges credits, and employers see "Credits can't be bought on this site yet" instead of a Buy button.

What credits pay for

Charge What it covers Cost
Job post Posting a job to a paid board, resubmitting, and moving boards The board's Credit Cost Per Job (default 0)
Featured upgrade Making a job Featured Settings -> Credits -> Featured upgrade (default 10)

Both costs pass through the wcbp_consumer_cost filter. The tiered pricing matrix uses it so paid members can post for less or for free. See Featured upgrade.

Credit ledger

Every change to a balance is a row in an append-only ledger. Rows are never edited or deleted, and the balance is the sum of the rows.

Type Effect
topup Credits added (purchase, mapped product, admin top-up)
hold Credits reserved when a job is submitted
deduction Credits spent (job live), or removed by an admin deduction or a payment refund
refund A held amount returned
expiry Credits removed because a pack's expiry passed

What employers see

  • Their balance in the dashboard and on the Credits tab.
  • A low-balance banner once the balance falls to the Low Balance Alert number (default 5, set 0 to turn the banner and the email off). It shows only for employers who already have credit history.
  • The same panel on any page with the [wcbp_credit_balance] shortcode or the Credit Balance block. See Pro blocks reference.

Free job posts

Leave a board's credit cost at 0 and posting stays free. You can charge later by setting a cost.

Where next

Direct payment gateways (Stripe and PayPal)

You can sell credits straight through Stripe Checkout or PayPal without running a store plugin. You paste your keys and a webhook URL, and employers pay on the hosted Stripe or PayPal page, so card details never reach your site.

If you already sell through WooCommerce, PMPro or MemberPress, use the WooCommerce, PMPro or MemberPress guides instead. You do not need a direct gateway as well.

Where the settings live

  1. Go to WP Career Board -> Settings -> Credits.
  2. Scroll to the Direct payment gateways card.
  3. Open the Stripe or PayPal block. A gateway you turned on shows an Enabled badge.

Each block shows its own Webhook URL, ready to copy.

Set up Stripe

Field Notes
Enable Stripe Turns the gateway on. Stripe is available only when this is on and a secret key is set.
Mode Test or Live.
Publishable key (active mode) From Stripe -> Developers -> API keys.
Secret key (active mode) From the same screen.
Webhook signing secret The whsec_... value Stripe shows after you add the webhook endpoint.
Post-purchase redirect Optional. Where the buyer lands after paying.
Cancel-redirect URL Optional. Where the buyer lands if they cancel.

Add the Stripe webhook

The webhook URL looks like this:

https://yourdomain.com/wp-json/wbcom-credits/v1/wp-career-board/webhook/stripe
  1. In Stripe go to Developers -> Webhooks -> Add endpoint and paste the URL.
  2. Select these events:
    • checkout.session.completed
    • charge.refunded
    • checkout.session.async_payment_succeeded (needed if you accept delayed payment methods, so credits land when the payment clears)
  3. Copy the endpoint's signing secret into Webhook signing secret.

The webhook credits the account even if the buyer closes the page after paying, and it is how refunds made in Stripe reach the ledger.

Set up PayPal

Field Notes
Enable PayPal Turns the gateway on. PayPal is available only when this is on and a Client ID and Client secret are set.
Mode Sandbox or Live.
Client ID From developer.paypal.com -> Apps & Credentials (Merchant REST app).
Client secret From the same app.
Webhook ID The ID of the webhook you create in the PayPal app (below). Required.
  1. Create a Merchant REST app at developer.paypal.com -> Apps & Credentials and copy the Client ID and secret into the fields above.
  2. In App settings -> Features, tick Accept payments and Refund.
  3. In App settings -> Webhooks, add the webhook URL below and copy its Webhook ID into the Webhook ID field.
https://yourdomain.com/wp-json/wbcom-credits/v1/wp-career-board/webhook/paypal

Select these events:

  • PAYMENT.CAPTURE.COMPLETED
  • PAYMENT.CAPTURE.REFUNDED
  • CHECKOUT.ORDER.APPROVED (takes the payment for a buyer who approves in PayPal but never returns to your site)

What happens on a purchase

  1. The employer starts a credit checkout and is sent to the hosted Stripe or PayPal page.
  2. After payment, the gateway sends the webhook to your site. The signature is checked before anything is credited.
  3. The credits are added to the employer's ledger as a topup and the balance updates.
  4. If you refund the payment from the provider dashboard, the credits that purchase gave are removed (a deduction row) and the employer gets a credit refund email.

A webhook delivered twice does not credit twice.

Test before you go live

For Stripe, set Mode to Test, use test-mode keys, and pay with the test card 4242 4242 4242 4242 (any future expiry, any CVC). Check that a topup row appears in the employer's ledger.

For PayPal, set Mode to Sandbox and use a sandbox app and a sandbox buyer account.

Keep test and live credentials separate. Switching Mode to Live makes the next purchase a real charge.

Credit packages and costs

You can decide what employers pay you for credits (packages) and how many credits a job post costs them. This page covers both.

There is no separate "Credit Packages" menu. Credits are sold through a Stripe or PayPal checkout (packs in Settings -> Credits) or through a WooCommerce product, PMPro level or MemberPress membership mapped to a credit amount.

Ways to sell credits

A credit package is whatever you sell that grants credits:

For products, levels and memberships, connect each one to a credit amount in WP Career Board -> Settings -> Credits -> Credit mappings. A completed purchase then adds that many credits to the employer's ledger.

Example of tiered WooCommerce products:

Product Credits Price Per-credit cost
Starter 3 credits $29 $9.67
Growth 10 credits $79 $7.90
Agency 25 credits $149 $5.96

Create one product per tier, then add one credit mapping per product.

Credit packs and custom amounts

Under WP Career Board -> Settings -> Credits -> Credit packs & pricing you define what employers can buy through the native Stripe or PayPal checkout.

  • Fixed packs. Add a row for each pack with the number of Credits and a Price. Each pack shows as a selectable card in the Buy Credits panel. Fill in a blank row to add a pack. Blank rows are ignored.
  • Custom amount. Turn on Allow custom amount to let employers type any number of credits between your Minimum credits and Maximum credits, priced at your Price per credit.
  • Currency. Set once for the packs and the custom-amount rate. Prices use the currency's own decimals.
  • Expire after (days). Optional, per pack. Leave it blank for credits that never expire. See Checkout, receipts and emails.

You can offer packs, a custom amount, or both. This pricing only feeds the native checkout. Products, levels and memberships keep their own credit mappings.

See Native Buy Credits checkout for what employers see.

Set the job-post cost

Posting a job is free until a board has a credit cost.

  1. Go to WP Career Board -> Settings -> Boards and edit a board.
  2. In the Board Settings box, set Credit Cost Per Job.
  3. Update the board.

The cost is per board, so different boards can charge different amounts. The check at submit and the credit hold use the same value, so what an employer is quoted is what is held.

A board with a credit cost above 0 shows its jobs as Featured automatically.

Bring back an expired job

Bringing an expired or closed job back onto a paid board charges credits again as a new listing period. The board's cost is held, then deducted, and the ledger records it. A free board (cost 0) charges nothing. Developers can change the price with the wcb_job_republish_credit_cost filter, for example to make renewing cheaper than posting again.

Tiered pricing by membership

You can discount or waive the board cost per BuddyPress member type, PMPro level or MemberPress membership with the tiered credit pricing matrix. The cheapest applicable tier wins.

Keep posting free

Leave the board credit cost at 0 (the default). You can switch a board to paid later by setting a cost.

Where employers see their balance

  • The employer dashboard.
  • The Credit Balance block or [wcbp_credit_balance] shortcode on any page.

When the balance is too low to post to a paid board, the submit is rejected before the job is created. Where credits can be bought, the employer is offered a way to buy them on the Credits tab (see the setup checklist).

Add or remove credits by hand

Use WP Career Board -> Settings -> Credits -> Admin credit adjustment. See Manual adjustments and refunds.

View the credit ledger

Every top-up, hold, deduction, refund and expiry is recorded in an append-only ledger. An employer sees their recent history in the Transaction History of the Credits tab and the Credit Balance block. The same data is available over the REST API at GET /wcb/v1/employers/{id}/credits, which returns the balance and the latest 50 rows. An employer can read their own; administrators can read any.

Selling credits through WooCommerce

You can sell credit packs as WooCommerce products. WooCommerce takes the payment with any gateway you have set up, and Career Board Pro adds the credits to the employer's balance once the order is paid. You can also sell recurring credits with WooCommerce Subscriptions.

Use this guide when:

  • You already have a WooCommerce store.
  • You want employers to buy credits like any other product (cart, checkout, orders page).
  • You want monthly credits, for example "10 credits per month".

Before you start

  • WooCommerce is installed and active, with at least one payment gateway set up (WooCommerce -> Settings -> Payments).
  • WooCommerce Subscriptions is installed if you want recurring packs.
  • To charge for posting, set a credit cost on a board. See Credit packages and costs. Selling packs works whether or not posting charges credits.

Step 1: Create a credit product

  1. Go to Products -> Add New.
  2. Name it, for example "10 Job Posting Credits", and set the Price.
  3. Leave the type as Simple product, or choose Simple subscription for recurring credits.
  4. Optionally mark it Virtual.
  5. Publish it.

Step 2: Map the product to a credit amount

  1. Go to Career Board -> Settings -> Credits and find the Credit mappings card.
  2. In Product / Plan, pick your product. Products are grouped by source, so WooCommerce products sit under a "WooCommerce" heading and subscription products under "WooCommerce Subscriptions".
  3. Enter the number of Credits, for example 10.
  4. Click + Add Mapping.

The mapping appears in the table (Provider, Product / Plan, Credits) with a Remove button. Add one mapping per credit pack.

The Detected providers card lists each supported source as active or not installed. A source that is not installed does not offer products to map.

Step 3: Check what employers see

Make sure Product mapping is on under Payment methods on the same tab. The employer's Credits tab then lists the product under Buy through the store, with a Buy button that opens the product page.

Step 4: Test the flow

  1. Log in as an employer.
  2. Open the Credits tab of the employer dashboard and note the balance.
  3. Click Buy on the product and complete the WooCommerce checkout.
  4. When the order is paid, return to the dashboard. The balance shows the new credits and the ledger has a topup row.

When credits are added

  • The order must be paid. An order that has not been paid, such as cash on delivery that is still processing, does not add credits until payment is recorded.
  • The buyer must be logged in. A guest order is not credited.
  • The credits are the mapped amount times the quantity ordered.
  • Each order is credited once, even if WooCommerce reports the status change more than once.

Refunds and cancellations

When a WooCommerce order is refunded or cancelled, Career Board Pro takes back the credits that order gave, in proportion to the refund. It takes back only credits the employer has not spent yet, and the balance never goes below zero. A partial refund removes a matching share. The employer gets a credit refund email.

Recurring credits with WooCommerce Subscriptions

  1. Install WooCommerce Subscriptions.
  2. Create the product as a Simple subscription.
  3. Map it under Credit mappings. It appears under "WooCommerce Subscriptions" in the Product / Plan list.
  4. Set the credits added on each successful payment.

Credits are added when the subscription is first paid and on every renewal payment.

Troubleshooting

Order completed but credits did not add. Check that the product has a mapping row, that Product mapping is on, that the order was placed by a logged-in customer, and that the order shows a payment date.

An employer bought before the product was mapped. The order is not credited later. Add the credits with an admin adjustment.

Granting credits with Paid Memberships Pro

You can give employers job-posting credits when they join a Paid Memberships Pro level, and again on each renewal. This suits plans like "Gold: 100 credits a month, Silver: 25 a month".

Use this guide when:

  • You already use Paid Memberships Pro on your site.
  • You want credits granted automatically when a member gets a level.

Before you start

  • Paid Memberships Pro is installed and active, and you have at least one level.
  • To charge for posting, set a credit cost on a board. See Credit packages and costs.

Step 1: Map a level to a credit amount

  1. Go to Career Board -> Settings -> Credits and find the Credit mappings card.
  2. In Product / Plan, pick the level. PMPro levels sit under the "Paid Memberships Pro" heading. If PMPro shows as not installed in the Detected providers card, its levels are not offered here.
  3. Enter the credits granted, for example 100.
  4. Click + Add Mapping.

Repeat for each level.

Step 2: How the grant works

  • When a member gets the level (checkout or a level change), the mapped credits are added once. Getting the same level again on the same day does not add them twice.
  • On each renewal payment of a recurring level, the same credits are added again.
  • On cancellation or expiry, nothing is removed. The member keeps their balance. To take credits back, use a manual adjustment.

Employers can also see the level on the Credits tab under Buy through the store. Buy opens that level's PMPro checkout.

Step 3: Test the flow

  1. Check out for the mapped level with a test member.
  2. Open the Credits tab of that member's employer dashboard. The balance shows the mapped amount.
  3. Transaction History shows a top-up for it.

Credits add up

Credits accumulate. If Gold gives 100 a month and the employer posts nothing, they have 300 after three months. Balances do not reset on renewal. To reset one, use a manual adjustment to deduct the leftover or top up to the target.

Common patterns

A free trial, then a paid plan. Create a free level and map it to 5 credits. Create a paid level and map it to 100. A member who upgrades ends up with 5 + 100 = 105 credits. To leave them with only 100, deduct the 5 with a manual adjustment.

Annual plans. Each renewal payment adds the mapped credits, whatever the billing cycle.

Troubleshooting

A member joined but got no credits. Check that the level has a mapping row and that PMPro shows as active in Detected providers. A cancellation (no level) never adds credits.

A renewal added no credits. Renewal credits follow PMPro's recurring payment record. Check the payment in PMPro first.

Granting credits with MemberPress

You can give employers job-posting credits when a MemberPress transaction completes, and again on each recurring payment. It works like the PMPro guide.

Use this guide when:

  • You use MemberPress to manage members.
  • You want credit allotments tied to memberships.

Before you start

  • MemberPress is installed and active, and you have at least one membership.
  • To charge for posting, set a credit cost on a board. See Credit packages and costs.

Step 1: Map a membership to credits

  1. Go to Career Board -> Settings -> Credits and find the Credit mappings card.
  2. In Product / Plan, pick the membership. MemberPress memberships sit under the "MemberPress" heading. If MemberPress shows as not installed in the Detected providers card, its memberships are not offered here.
  3. Enter the credits granted, for example 50.
  4. Click + Add Mapping.

Step 2: How the grant works

  • When a transaction completes for the membership, the mapped credits are added once per transaction.
  • On each recurring payment, the new transaction adds the credits again.
  • On cancellation or expiry, nothing is removed. To take credits back, use a manual adjustment.

The employer's Credits tab lists the membership under Buy through the store. Buy opens the membership page.

Step 3: Test the flow

  1. Subscribe to the mapped membership with a test account.
  2. Open the Credits tab of that member's employer dashboard. The balance shows the mapped amount.
  3. Transaction History shows a top-up for it.

Common patterns

A trial plus a paid plan. Create a free trial membership mapped to 5 credits and a paid one mapped to 50. Each completed transaction adds its own mapped credits.

One-time membership, one-time grant. Map a non-recurring membership. The member gets the credits once and keeps them until they are spent.

Read a balance in code. The balance is the sum of the ledger, not a user-meta value. Read it with \Wbcom\Credits\Credits::get_balance( 'wp-career-board', $user_id ) or over REST at GET /wcb/v1/employers/{id}/credits.

Troubleshooting

A member paid but got no credits. Check that the membership has a mapping row and that MemberPress shows as active in Detected providers.

A payment is still pending. Credits are added only when MemberPress marks the transaction completed. If it is still pending, check the payment gateway first.

Manual adjustments and refunds

You can add or remove credits for any employer by hand, refund native Stripe or PayPal purchases, export the whole credit ledger, and handle privacy requests. Use manual adjustments when the automatic flow does not cover a case: a comp credit, a migration, an order placed before you mapped the product, or a chargeback.

Add or remove credits

Go to WP Career Board -> Settings -> Credits and scroll to the Admin credit adjustment card.

  1. Enter the employer's User ID.
  2. Enter the number of Credits.
  3. Set Type to Top-up (add) or Deduct (remove).
  4. Enter a Note with the reason, for example "Comp for support ticket" or "Migration grant".
  5. Click Apply.

The ledger gets a topup row with the note "Admin top-up: your note", or a deduction row with "Admin deduction: your note". The employer's balance updates. After you apply, the card shows "User #N balance: X credits" so you can confirm the result.

You need permission to manage Career Board settings. Administrators have it by default.

Return credits for a job

Job posting uses a hold, then a deduction or a refund, so most returns are automatic:

  • If you reject a pending job, or a job is trashed or deleted before it goes live, the held credits go back to the employer (a refund row) and they get a credit refund email.
  • If a job was already approved and you later need to return the credits, use the adjustment card with Type: Top-up and a note that names the job.

Ledger history

Every manual action writes a ledger row with the credit amount, the entry type, your note and a timestamp. Rows are never edited or deleted. If you make a mistake, add a reversing entry with a clear note.

When a user account is deleted, the ledger rows stay, with the link to the user removed. Deleting an employer erases their alerts, notifications and AI matching data.

Export the ledger

Go to WP Career Board -> Settings -> Analytics. Once there is credit activity, the Credits card has an Export Credit Ledger (CSV) button. It downloads every ledger row, newest first, with the columns ID, Employer, Amount, Type, Job, Note, Date. "Employer" is the user ID and "Job" is the related job ID.

The same file is available at GET /wp-json/wcb/v1/analytics/credits.csv for administrators and for any role granted the wcb/view-analytics or wcb/manage-credits ability.

Review and refund native checkout purchases

WP Career Board -> Settings -> Analytics also has a Transactions card. It lists every Stripe and PayPal purchase and refund made through the native checkout.

  • The list shows 20 rows per page. Filter it by All, Purchases or Refunds.
  • Each row shows the date, employer, gateway, type, credits, amount and status (Paid, Partially refunded or Refunded). Paid rows link to their receipt.
  • A purchase that can still be refunded has a Refund button. Click it, then choose Confirm refund or Cancel on the spot. Confirming asks Stripe or PayPal to issue the refund. The credits are removed once the provider confirms it.
  • Purchases made through WooCommerce, PMPro or MemberPress do not appear here. Use the adjustment card for those.

Refund a store purchase

When a customer charges back or you refund a credit-pack order:

  • WooCommerce. Refunding or cancelling the order takes back the credits it gave, as far as the employer has not spent them. See WooCommerce.
  • PMPro and MemberPress. Credits are not removed automatically. Confirm the refund in the membership plugin, then deduct the credits with the adjustment card and a note such as "Chargeback on order X".
  • Stripe and PayPal. A refund from the provider dashboard removes the credits that purchase gave. See Direct payment gateways.

Privacy requests

Pro adds its data to the WordPress Export Personal Data and Erase Personal Data tools. A member deleting their own account, or an admin deleting a user, also erases it.

What Export Erase
Resumes (fields and content) Yes Deleted, including the photo
Job alerts of a signed-in member Yes (query, filters, frequency) Deleted
Bell notifications Yes (up to 1,000) Deleted
Push devices No Deleted
AI matching data for the person No Deleted
Credit ledger No Kept for accounting. The link to the person is removed only when the account is being deleted

On an account that stays open, erasing keeps the ledger linked, because unlinking would wipe the credits the member paid for. When rows are kept on account deletion, the tool reports "Credit ledger entries are retained (anonymized) for accounting/tax obligations."

Troubleshooting

A customer disputes a deduction. The ledger row carries your note and timestamp. If it was a mistake, add a reversing top-up. Never try to edit or delete the original row.

Native Buy Credits checkout

You can let employers buy credits right on the Credits tab of their dashboard. They pick a pack (or a custom amount), choose Stripe or PayPal, and pay on the hosted payment page. The same panel appears in the Credit Balance block.

Two ways to sell

Native checkout Product mapping
Where the buyer pays The Credits tab, then the hosted Stripe or PayPal page Your WooCommerce, PMPro or MemberPress checkout
What you set up Gateway keys and webhook, credit packs or a custom-amount rate A Credit mapping from a product or plan to a credit amount
Tax, coupons, receipts Built in (see Checkout, receipts and emails) Handled by the store plugin

You can use both at once. The Credits tab lists the gateway packs first, then Buy through the store for each mapped product.

Turn it on

Go to WP Career Board -> Settings -> Credits and:

  1. Under Payment methods, turn on Native checkout ("Allow Stripe / PayPal hosted checkout"). The other toggle, Product mapping, controls the store route and is independent.
  2. Set up at least one gateway in the Direct payment gateways card. See Direct payment gateways.
  3. Under Credit packs & pricing, define what you sell: fixed packs, a custom-amount rate, or both. See Credit packages and costs.
  4. Optional: set billing details, tax and coupons. See Checkout, receipts and emails.

The Buy panel appears once native checkout is on, a gateway is enabled with keys, and there is a pack or a custom-amount rate to sell.

What the employer sees

Employers open the Credits tab of their dashboard, or a page with the Credit Balance block or [wcbp_credit_balance]. Buy Credits next to the balance opens a panel with:

  • A Payment method row with each available gateway.
  • One card per credit pack, showing credits, price and, when set, how long the credits last.
  • A Custom amount (credits) field when custom pricing is on, with the price updating as they type, between your minimum and maximum.
  • Billing details (name, email and country, or the full address if you chose that).
  • A Coupon code field.
  • A note when you charge tax.
  • Continue to payment, which sends them to the hosted Stripe or PayPal page.

The price is worked out on the server. Nothing the browser sends decides the charge.

Below the panel the tab shows Awaiting payment (purchases that have not cleared yet, added as soon as the payment clears), Receipts with View receipt links, and the Transaction History with Show more (Top-up, Hold, Deduction, Refund, Expired).

After payment

After paying or canceling, the buyer lands back on the Credits tab:

  • Paid: "Payment received - confirming your credits..." The page checks the balance until the top-up shows, then says "Credits added to your balance." If it takes long it says "Confirming - your balance updates shortly."
  • Canceled: "Checkout canceled - you were not charged."

The signed webhook from Stripe or PayPal is what adds the credits (see Direct payment gateways), and the page also claims the payment when the buyer returns. If the employer closes the tab early, the webhook still credits the account. Delayed payment methods stay under Awaiting payment until they clear.

Checkout, receipts and emails

You can add tax, collect billing details, offer coupons and give buyers numbered receipts for credit purchases. This page also lists the emails the credit system sends.

The billing, tax, receipt and coupon settings apply to purchases made through Stripe or PayPal. Purchases through WooCommerce, PMPro or MemberPress use that plugin's own checkout, tax and invoices.

Checkout and receipts

Find these under Settings -> Credits -> Checkout & receipts.

Setting What it does
Billing details Name, email and country (default) or Full postal address (for invoices). Company and VAT / GST number are always optional.
Tax rate (%) Added on top of the pack price at checkout. Default 0 (no tax).
Tax label Shown on receipts, for example VAT or GST. Blank shows "Tax".
Business name Shown at the top of receipts. Blank uses the site name.
Business address Shown on receipts.
Your VAT / GST number Shown on receipts.
Receipt number prefix Default INV-.

When a tax rate is set, the Buy panel tells the employer that prices exclude tax and that it is added at checkout.

Coupons

Find these under Settings -> Credits -> Coupons. Fill in a blank row to add a coupon. Clear a coupon's code to delete it.

Column Meaning
Code What the employer types in the Coupon code field
Discount Percent off or Amount off (in the pack currency)
Amount The percent or the amount
Expires Optional date
Usage limit Optional cap on total uses
Used How many times it has been used
Active Turn a coupon off without deleting it

An invalid, expired or used-up code shows an error on the employer's Buy panel and the checkout does not start.

Receipts

Every paid Stripe or PayPal checkout gets a numbered receipt with the amount charged, coupon, tax, the buyer's billing details and your business details.

  • Employers find receipts on the Credits tab of their dashboard, under Receipts. View receipt opens a printable page that only the buyer and administrators can open.
  • Each purchase also emails a receipt (see below).
  • Developers can restyle the page with a theme template at wbcom-credits/wp-career-board/frontend/receipt.php.

Prices show with the right number of decimals for the pack currency (for example none for JPY).

Credits that expire

In the pack editor, Credits expire after (days) makes a pack's credits expire that many days after purchase. Leave it blank for credits that never expire. When credits expire, an expiry row is written to the ledger and the Credits tab history shows Expired.

Emails

Edit subjects and bodies under Settings -> Emails. Employers can turn off the optional ones under Email Notifications in their dashboard account settings.

Email Sent to When Employer can turn off
Credit Purchase Receipt Employer A Stripe or PayPal purchase completes. Goes to the billing email if the buyer gave one. No
Credit Top-Up Confirmation Employer Credits are added by a mapped product or membership. A Stripe or PayPal purchase sends the receipt instead. No
Credit Refund Employer A held amount is returned because the job did not go live, or a payment is refunded and its credits are removed. Shows the new balance. No
Low Credit Balance Warning Employer The balance falls to the Low Balance Alert number, once each time it crosses below Yes
Featured Listing Ended Employer A job's Featured period ends Yes

The employer also gets a bell notification when a Featured period ends.

Multi-board

Run unlimited independent job boards from one site.

Multi-board

You can run more than one job board on one site, for example "Tech Jobs" and "Marketing Jobs". Each board can have its own pricing, approval rule, listing length, currency and hiring stages, and all boards are managed from one admin.

What you can do

  • Create boards. Add as many boards as you need.
  • Let employers pick a board. When more than one board exists, the job form shows a Post to Board dropdown.
  • Let visitors filter by board. The Job Filters can include a board filter, so visitors can narrow the Job Listings block to one board.
  • Show one board on a page. The Job Listings block accepts a boardId attribute that limits it to a single board.
  • Set rules per board. Each board has its own credit cost, moderation, listing length and currency, and its own pipeline stages.

Create a board

  1. Go to Career Board → Settings → Boards.
  2. Click Add Board, or Add Your First Board when the list is empty.
  3. Enter a Title. Employers see it when they post a job. You can add a description in the content area.
  4. Set the board's rules in the Board Settings box, in the main column of the edit screen. See Board settings.
  5. Click Publish.

A new board gets the default hiring stages when you publish it.

The Boards tab lists your boards, 20 per page, with a search box. Each row shows the board name, its jobs, its pipeline stages and its credit cost, with Edit and Delete actions.

Delete a board

Click Delete on the board's row and confirm. Deleting a board:

  • removes the board and its pipeline stages permanently;
  • keeps its jobs. They are no longer assigned to that board.

The dialog reports how many stages were removed and how many jobs were unlinked.

Board settings

Open a board with Edit to set:

Setting Default What it does
Credit Cost Per Job 0 Credits held when a job is submitted to this board and spent when it goes live. 0 means free posting. Moving a job to another board re-prices it. See Credit system.
Moderation Use global default Choose Auto-publish or Requires approval for this board, or follow the site-wide Auto-publish jobs setting.
Listing length (days) 0 How long a job stays open when the employer sets no deadline. 0 follows Default listing length (days) under Settings > Jobs.
Currency Site default The currency for salaries on this board.

Jobs on a board with a credit cost above 0 are marked as Featured in job listings.

The map provider is set for the whole site under Career Board → Settings → Integrations. It is not set per board.

Pipeline stages per board

Each board has its own hiring stages. The Application Kanban uses the stages of the board a job was posted to. The Boards tab shows each board's stage count and a Manage button. See Application pipeline.

Field Builder groups can be hidden on chosen boards. See Field Builder overview.

Default board

Career Board creates a default board called Main Board, so a job always has a board. The Boards tab has no action to choose a different default board.

Employers and boards

By default the Post to Board dropdown lists every published board. The BuddyPress group boards integration limits the list to boards of groups the employer belongs to. The wcb_board_options_for_employer filter changes the list.

Filter by board

The board filter in the Job Filters lists up to 20 published boards, sorted by name. The wcb_job_listings_board_options filter changes the list.

Job Feed

RSS, JSON, and XML feeds for every board.

Job Feed - Overview

You can publish your live jobs as an XML feed and give the address to job aggregators, so they list your jobs and keep them up to date.

Turn the feed on

  1. Go to Career Board → Settings → Job Feed.
  2. Turn on Enable Feed.
  3. Enter a Contact Email. It goes in the <email> field of every job. It defaults to your WordPress admin email.
  4. Save. The Feed URL row shows the address, with View Feed and Copy URL buttons.

The feed address is:

https://yoursite.com/wcb-jobs.xml

Submit that address to any aggregator that accepts an Indeed-style XML feed. The feed is off by default.

To turn it off, switch Enable Feed off. The address then returns your theme's 404 page with an HTTP 404 status, and aggregators stop receiving your jobs.

What the feed contains

The feed has one <source> element that holds <publisher> (your site title) and <publisherurl> (your home address), followed by one <job> for each published job, newest first.

Each <job> has:

Field Value
<title> Job title
<date> Publication date, in RFC-822 form, GMT
<referencenumber> The job's post ID
<url> The job's public address
<company> Company name
<city> The job's first location
<country> Always present, empty
<description> The job description as plain text, with HTML removed
<salary> Salary range with the job's own currency symbol, for example $80,000 - $120,000 / yearly. Empty when the job has no salary.
<jobtype> The job's first job type
<email> The Contact Email from the settings
<expirationdate> The job's application deadline

More than 200 jobs

Each feed page holds up to 200 jobs. Add a start parameter to read further pages:

https://yoursite.com/wcb-jobs.xml?start=0     jobs 1 to 200
https://yoursite.com/wcb-jobs.xml?start=200   jobs 201 to 400
https://yoursite.com/wcb-jobs.xml?start=400   jobs 401 to 600

Caching

Each feed page is cached for one hour, and the response tells CDNs and aggregators they may cache it for one hour too. When any job is saved, the next request builds a fresh feed, so you never need to clear anything by hand.

Analytics

Credit, job, and applicant analytics with CSV export.

Analytics

You can see how your board is performing and how credits are flowing, in one place. Open Career Board > Settings > Analytics.

Engagement

Figure What it counts
Job Views (30 days) Job page views recorded in the last 30 days
Applications per Job Total applications divided by published jobs
Total Applications Submitted applications. Links to the Applications screen.
Published Jobs Live jobs. Links to the Jobs screen.

Top jobs by views lists the five most-viewed published jobs from the last 30 days, with their view counts. Until candidates have opened listings it shows "No view data yet". Job views are recorded by the Free plugin; if its views table is missing, view figures show 0.

Credits

The Credits card shows figures once there is credit activity. Until then it says "No credit activity recorded yet".

Figure What it counts
Credits Issued Lifetime total of all topup rows
Credits Spent What paid jobs actually cost: the net of holds, releases and deductions on jobs that were charged. Returned holds and price changes are already netted out.
Outstanding Balance The sum of every employer's balance, straight from the ledger
Revenue (CODE, after refunds) Money taken through Stripe or PayPal checkout, minus refunds, one figure per currency. Store purchases (WooCommerce, PMPro, MemberPress) are not included.

Export Credit Ledger (CSV) downloads the whole ledger.

Caching

Figures are refreshed every five minutes. A credit top-up or a credit charge refreshes the credit figures straight away.

CSV export

GET /wp-json/wcb/v1/analytics/credits.csv

The file is named wcb-credits-YYYY-MM-DD.csv, streamed newest first in pages of 5,000 rows, so it works on a very large ledger. It needs the wcb/view-analytics or wcb/manage-credits ability, which administrators have.

Column Meaning
ID Ledger row ID
Employer User ID on the row (0 once an account was deleted and the row anonymised)
Amount Positive for credits added, negative for credits taken
Type topup, hold, deduction, refund or expiry
Job The related item ID, normally the job
Note Note attached to the row
Date When the row was written

Transactions

The same tab has a Transactions card: a paged list of Stripe and PayPal purchases and refunds, which you can filter by All, Purchases or Refunds, with a refund action. See Admin Transactions view.

Notes

  • Ledger rows are added, not edited, so the export is a reliable record. When an account is erased through the privacy tools, its rows are kept with the employer set to 0.
  • Analytics are site-wide. There is no per-board view.

AI Features

AI-assisted job description writing.

AI features

You can help candidates find jobs and help employers review applicants with AI. The plugin works fully without it. Add a provider key under Career Board > Settings > AI Settings and the tools below turn on.

  • AI Chat Search - candidates search jobs in plain language.
  • Recommended jobs - matches for each candidate, based on their resume.
  • Applicant ranking - a 0-100 fit score and a one-line reason per applicant.
  • Applicant summary - a one or two sentence summary of each candidate.
  • Cover letter writer - candidates draft a letter in the apply panel.
  • Description writer - "Generate with AI" on the post-a-job form.

Step-by-step guides for candidates and employers, and AI troubleshooting, are in the WP Career Board (Free) docs under AI features: Overview, Setup and providers, Candidate AI features, Employer AI features, and Troubleshooting. This page covers the Pro side.

Where each feature lives

Feature Surface
Job embeddings Created when a job is created, if an embedding provider is set. Index existing jobs (AI Settings tab) backfills the rest.
AI Chat Search Block wcb/ai-chat-search, shortcode [wcbp_ai_chat_search], POST /wcb/v1/ai/match
Recommended jobs POST /wcb/v1/ai/match and GET /wcb/v1/candidates/{id}/matches
Applicant ranking Employer dashboard and GET /wcb/v1/ai/ranked-applications/{job_id}
Cover letter "Generate" in the apply panel and POST /wcb/v1/jobs/{job_id}/ai-cover-letter
Description writer Post-a-job form and POST /wcb/v1/jobs/ai-description

Providers are chosen per task

Choose one provider for analysis and one for matching. Each has its own key and model.

Task Providers Notes
Analysis and ranking (ranking, summaries, cover letters, descriptions, chat) Anthropic Claude, OpenAI, Ollama Claude defaults to Sonnet
Matching (embeddings) OpenAI, Ollama Claude has no embeddings, so it is not offered here
Provider Fields Defaults
OpenAI API key, model (GPT-4o mini or GPT-4o), embedding model (3-small or 3-large) GPT-4o mini, text-embedding-3-small
Anthropic Claude API key, model (Haiku, Sonnet or Opus) Sonnet
Ollama (self-hosted) URL, model, embedding model. No key. http://localhost:11434, llama3, nomic-embed-text

Fastest setup: one OpenAI key, with OpenAI chosen for both Analysis and Matching. Ollama keeps all data on your server but needs server CPU or GPU. Developers can add a provider: see AI providers and endpoints.

Applicant ranking

  • What the model reads: the job title and description, the cover letter, the screening answers from the Field Builder, and the resume the candidate applied with (their profile resume if they chose none). Guests are scored on what they sent. An uploaded PDF CV is not read.
  • Auto-score applicants on submit (off by default): each new application is scored in the background about 30 seconds after it arrives, using one model call.
  • Rank on demand: the ranking button returns applicants already scored at once, lists the rest as Not scored, and queues them. Scoring runs in batches of 25 in the background. Newly scored applicants appear the next time the dashboard loads. Only the newest 500 applications of a job are ranked per pass.
  • Not scored: if the provider is down or replies with nothing usable, the applicant shows Not scored, not 0%. Nothing is saved and scoring is retried up to three times, after 5, 10 and 20 minutes.
  • Cost: scores, reasons and summaries are saved on each application, so reopening the dashboard never bills the model again.

Telling applicants

Career Board > Settings > AI Settings > Tell applicants shows applicants "Employers on this site may use AI to help review and rank applications." in the job page apply panel. It shows only while an analysis provider is set up. It is on for new installs and off for sites upgraded from before 1.8.0, where an admin notice lists it as a recommended safer default.

Cover letters

The cover letter writer uses the signed-in candidate's resume and the job's title and description (first 2,000 characters). It works only for published jobs, so a draft or pending job never leaks into a letter. Candidates need permission to apply for jobs.

Limits

  • Each signed-in user can make 30 AI requests per hour across the AI routes. After that the route returns 429.
  • Matching is computed in PHP over the newest 2,000 jobs with embeddings. Developers can change that with the wcbp_ai_match_scan_cap filter.
  • No resume file parser. Resume text for matching comes from the candidate's resume fields.
  • No "Test connection" button: check a provider by generating a description on the post-a-job form.
  • No WP-CLI AI commands.

Notifications

Email and BuddyPress notification templates.

Notifications

You can keep employers, candidates and administrators informed through the notification bell, send job alert and credit emails, and reach members on the companion app with push notifications.

The notification bell

The bell, its badge and dropdown come from the free plugin (Employer Dashboard and Candidate Dashboard blocks). Pro writes the rows.

Event Who gets it Message
Application submitted Employer "Jane Doe applied for Senior PHP Developer"
Application submitted Candidate "Your application for Senior PHP Developer was submitted"
Status changed Candidate "Your application for Senior PHP Developer is now Shortlisted"
Job removed Candidate "The job you applied to, Senior PHP Developer, was removed"
Job closed Candidate "The job you applied to, Senior PHP Developer, is now closed"
Job approved Employer "Your job "Senior PHP Developer" has been approved"
Job not approved Employer "Your job "Senior PHP Developer" was not approved"
Job expired Employer "Your job "Senior PHP Developer" has expired"
Job ending soon Employer "Your job "Senior PHP Developer" stops taking applications in 3 days"
Featured ended Employer ""Senior PHP Developer" is no longer featured"
Job reported Administrators "The job "Senior PHP Developer" was reported"
Member reported Administrators "Jane Doe was reported"

Notes:

  • Removed and closed jobs get their own sentence, not "is now Job removed". A candidate who withdraws their own application gets no notification.
  • Ending soon is sent 3 days before the job's deadline.
  • Reports notify up to 20 administrators. A job report notifies on the first report and again when the report count hides the job. A member report notifies on the first open report.
  • Dead links - if the job, company or resume a row points to was deleted or is no longer public, the row shows as plain text instead of a link. A closed or expired job keeps its public page, so its link still works.
  • Times show as relative times, such as "2h ago", in the site language.
  • Old rows are deleted with the free plugin's history retention setting.

The bell REST routes are GET /wcb/v1/notifications, DELETE /wcb/v1/notifications, DELETE /wcb/v1/notifications/{id}, POST /wcb/v1/notifications/{id}/read and POST /wcb/v1/notifications/read-all. All need a signed-in user and act only on that user's rows.

Push notifications

Every bell row is also sent as a push to the member's signed-in companion app devices, through Expo's push service. Push is sent in the background, so the action that caused it is not slowed down.

  • A device is registered when the member signs in to the app (POST /wcb/v1/push/register-device). A shared device that signs in as another member moves to the new account.
  • Devices Expo reports as no longer registered are removed.
  • Deleting a member's account removes their devices.

There is nothing to set up on the site. The web app does not send browser push. See PWA.

Pro emails

Pro adds these emails to the free plugin's email list. Turn each on or off and edit its subject under Career Board > Settings > Emails.

Email To When
Job Alert Digest (job-alert) Candidate Matching jobs for a saved alert
Confirm Job Alert (guest) (job-alert-confirm) Visitor A visitor saves an alert with an email
Credit Top-Up Confirmation (credit-topup) Employer Credits are added to an account
Credit Purchase Receipt (credit-receipt) Employer A credit purchase completes
Credit Refund (credit-refund) Employer Credits are refunded or removed
Low Credit Balance Warning (low-balance) Employer Balance falls to the low-balance level
Featured Listing Ended (featured-expired) Employer A job's featured period ends

Members can turn off the optional emails for themselves: Job Alert Digest, Low Credit Balance Warning and Featured Listing Ended. They do this under Email Notifications on the Account Settings tab of the Employer Dashboard or Candidate Dashboard. The other emails are always sent when enabled.

Featured Listing Ended has a bell row of its own, so its email does not add a second one.

Customize email templates

  • Theme override - put a file at your-theme/wp-career-board/emails/{email-id}.php. For example wp-career-board/emails/credit-topup.php.
  • Plugin templates - Add your own template folder with the wcb_email_template_dirs filter.

For developers

Whenever the bell creates a row, it fires wcb_notification_created with the row as the first argument and the community notification contract payload as the second. The payload is null for admin-only rows such as reports. A central inbox (BuddyNext or another add-on) can listen once and mirror every row:

add_action( 'wcb_notification_created', function ( array $row, ?array $contract ) {
    if ( null === $contract ) {
        return;
    }
    // recipient_id, type, actor_id, object_type, object_id, message, url, group_key, notification_id.
}, 10, 2 );

The payload is described in the free plugin's hooks reference under "Community notification contract". Pro declares one type of its own, job_featured_expired, with the wcb_community_notification_types filter. A candidate's own "application submitted" row has the candidate as its own actor, so it is not treated as a community event.

To keep an event from being announced twice, an add-on that records the same event returns false from wcb_email_announces_notification for that email and fires wcb_notification_created itself. The bell does this for the application, job approval, rejection, expiry, ending soon and featured ended emails.

PWA

Progressive Web App with installable manifest and service worker.

PWA

You can let visitors install your job board as an app and reopen job pages they have already viewed when the connection is poor.

What you get

Feature What it does
Web app manifest Lets browsers offer to install the board as an app.
Service worker Caches job, company and candidate pages so pages you have viewed load again quickly.
Brand colour The browser bar of the installed app uses your Brand colour.
Fresh forms Application forms and dashboards load from the network first.

There is nothing to switch on. It works as soon as Pro is active.

Set the colour

The installable app uses your Brand colour, the same colour as your emails and the mobile app. Go to Career Board > Settings > Brand to change it. The default is #4F46E5. The PWA settings card on the Integrations tab links to it.

Set a site icon

Go to Settings > General > Site Icon and upload a square image of at least 512 by 512 pixels. The manifest uses the 192 and 512 pixel versions. Without a site icon the manifest has no icons.

How it works

Two files are served from your site's address, including when the site lives in a subfolder:

  • /wcb-manifest.json - the app name (your site name plus "Jobs"), short name "Jobs", start page set to your jobs page (the page assigned under Career Board > Settings > Pages, or the home page if none is set), standalone display, white background and the Brand colour.
  • /wcb-service-worker.js - the service worker.

The plugin answers both, so you do not need to save permalinks. The manifest link and the service worker are added only on job archive pages, single job pages, and the jobs archive, employer dashboard and candidate dashboard pages you set under Career Board > Settings > Pages.

The service worker only handles requests for your jobs, companies and resumes pages and for the addresses of individual jobs, companies and resumes, whatever your site calls them:

  • Job, company and resume pages load from the cache when a copy exists, and the cache is refreshed in the background.
  • Any address with apply in the query string, or with dashboard in the path, goes to the network first and uses the cache only when offline.
  • The cache is named after the plugin version, so an update clears the old cache.

To change the manifest in code, use the wcbp_pwa_manifest filter.

Install the app

Browsers that support installing web apps can offer to install the board from the jobs pages. The installed app opens without the browser toolbar. Browsers that do not support service workers show the site as normal, without cached pages.

Push notifications

Push is for the native companion app, not for the browser. The PWA does not send browser push.

When a member signs in to the companion app, the app registers its Expo push token with POST /wcb/v1/push/register-device (fields expo_push_token and platform of ios or android). Every event that adds a row to the notification bell is then sent to that member's devices through Expo's push service. See Notifications.

Limits

  • The installed app opens on your jobs page. Pages outside your jobs, companies and resumes pages and the job, company and resume addresses are not cached.

BuddyPress Integration

Group boards, activity stream, tiered credit pricing, and notifications.

BuddyPress integration - overview

You can show jobs and applications inside your BuddyPress community: profile tabs for employers and candidates, a job board for each group, activity posts, notification-bell alerts, member directory filters, and group-admin moderation. You can also give paying members cheaper job posts.

BuddyPress must be active for the integrations below, except tiered credit pricing, which also works with Paid Memberships Pro or MemberPress alone.

What you can do

You can Needs Page
Add My Jobs (employers) and My Career (candidates) tabs to member profiles BuddyPress Profile tabs
Give each group its own job board and a Jobs tab BuddyPress Groups, and the Group Job Boards switch Group-scoped job boards
Post to the activity stream when a pending job is approved and when a candidate is hired BuddyPress Activity component Activity stream entries
Alert employers to new applications and candidates to status changes in the notification bell BuddyPress, with Profile Tabs on Notifications
Filter the member directory by Open to work and Hiring BuddyPress Members component Member directory filters
Charge a different credit cost by member type, Paid Memberships Pro level or MemberPress membership A saved price matrix Tiered credit pricing
Let group admins and moderators approve or reject jobs on their group's board Group Job Boards on Group-scoped moderation

Turn integrations on or off

Go to Career Board > Settings > Integrations and find the BuddyPress card. It has three switches:

  • Profile Tabs - on by default. Adds the My Jobs and My Career tabs. Turn it off if your BuddyPress theme already provides equivalent tabs.
  • Application Notifications - on by default. Sends in-app bell notifications, not emails. Email notifications are set under Settings > Emails.
  • Group Job Boards - off by default. Turn it on to give each group a job board and a Jobs tab. Groups you already have are added in the background.

If BuddyPress is not active, the card shows "Requires BuddyPress (not active)" and the switches are disabled.

The activity entries and the member directory filters have no switch. They run whenever the BuddyPress Activity or Members component is active.

Tiered credit pricing has no settings screen. See Tiered credit pricing.

What you do not need

  • No extra plugins beyond BuddyPress and WP Career Board Pro.
  • No manual board setup for groups. Each group board is created for you as a normal Career Board board.

Where to next

Group-scoped job boards

You can give every BuddyPress group its own job board. Each group gets a Jobs tab that lists only the jobs posted to that group's board. Your site-wide job board is not affected.

Group Job Boards is off by default, so a community with many groups does not get a board per group until you ask for it.

Turn it on

  1. Go to Career Board > Settings > Integrations.
  2. In the BuddyPress card, switch on Group Job Boards.
  3. Save.

After you switch it on:

  • Every new group gets a matching job board automatically.
  • Your existing groups are added as boards in the background, 50 groups at a time. You do not need to visit each group.
  • A Jobs tab appears in each group's navigation.

The background run skips groups that already have a board, so it never creates duplicates. A group whose page is opened before the run reaches it gets its board on the spot.

Turn it off

Switch Group Job Boards off and save. New groups stop getting boards and the Jobs tab is hidden. Boards already created are kept, and nothing is deleted. Switching it on again picks up where it left off.

What members see

The Jobs tab shows the standard job listing for the group's board. If the group has no board yet, the tab says "No jobs board for this group yet."

The board follows the group:

  • Renaming the group renames the board.
  • Deleting the group moves its board to the trash.

Post a job to a group

The group Jobs tab has no Post a Job button. Members post from the normal Post a Job page and choose the group's board there.

The board list only shows group boards for groups the member belongs to (as member, moderator or admin). Boards that are not tied to a group, such as your site-wide board, are always in the list. Site administrators see every board.

Let group admins moderate

Group admins and moderators can approve or reject jobs on their own group's board. See Group-scoped moderation.

To tie an existing board to a group instead of letting the plugin create one, set both links:

update_post_meta( $existing_board_id, '_wcbp_group_id', $group_id );
groups_update_groupmeta( $group_id, 'wcbp_board_id', $existing_board_id );

Activity stream entries

You can let your community see job news in the BuddyPress activity stream. When a pending job is approved, an entry is posted. When a candidate is marked hired, another entry is posted.

This works when the BuddyPress Activity component is active. There is no setting to switch it off.

What gets posted

When Entry type Where it shows
A pending job is approved on the site-wide board Job posted The site-wide activity feed
A pending job is approved on a group's board Job posted The group's activity tab and the site-wide feed
An application is moved to Hired Member hired The site-wide activity feed

Visitors can filter the activity directory by Job posted and Member hired.

The hired entry always goes to the site-wide feed. It is not posted into a group.

What the entries say

  • Job approval: "Acme Inc posted a new job: Senior Backend Engineer." The name links to the poster's profile and the title links to the job.
  • Hire: "Sarah Chen was hired for Senior Backend Engineer." The name links to the candidate's profile and the title links to the job. The entry starts with a celebration emoji.

What is not posted

  • Jobs that publish straight away without going through approval. Only a job moving from pending to published posts an entry.
  • Pending jobs, so your moderation queue stays private.
  • Application submitted, under review, shortlisted or not selected. Only Hired is public. Other status changes reach the candidate privately through the notification bell.

Change the wording

The entry text can be translated with any translation plugin, using the wp-career-board-pro text domain. There is no setting or filter for the wording.

Candidate and employer notifications

You can alert people in the BuddyPress notification bell when something happens to their application:

  • Candidates are alerted when the status of their application changes.
  • Employers are alerted when someone applies to one of their jobs.

These are in-app alerts, not emails. Email notifications are set separately under Career Board > Settings > Emails.

What candidates see

When an application's status changes, the candidate gets a bell notification worded "status - job title".

New status Text shown
Submitted Application received
Reviewing Your application is under review
Shortlisted You were shortlisted
Rejected Application not selected
Hired You were hired!
Any other status Application status updated

Clicking the notification opens My Applications in the candidate's My Career profile tab.

No notification is sent when the candidate withdraws their own application.

What employers see

When someone applies, the job's author gets a bell notification:

  • One application: "New application received for" and the job title.
  • Several stacked together: "N new applications received".

Clicking it opens the Applications screen in the employer's My Jobs profile tab. Applications from guests also notify the employer. An author who applies to their own job is not notified.

Turn it off

Go to Career Board > Settings > Integrations, open the BuddyPress card and switch off Application Notifications. It is on by default and turns off both kinds of alert.

Application Notifications only works while Profile Tabs is also on. Turning Profile Tabs off stops these alerts too.

Change the wording

The text can be translated with any translation plugin, using the wp-career-board-pro text domain. Statuses not in the table above show "Application status updated".

Member directory filters

You can let visitors narrow your BuddyPress members directory to people who are open to work, or to people who are hiring.

Three links appear above the member list:

  • All members - clears the filter.
  • Open to work - members with a published resume marked open to work.
  • Hiring - members who have at least one published job.

Clicking a link filters the member list in place. It keeps your theme's layout and paging. The filters work on the BuddyPress Members component, so it must be active. There is no setting to switch them off.

The links appear where your theme shows member-type tabs above the directory. If your theme does not output that area, the links do not show.

How the filters decide

  • Open to work looks at up to 500 published resumes that are marked open to work, and shows their authors.
  • Hiring shows every member who owns a published job.

If no one matches, the directory shows no members instead of showing everyone.

The filters use public, published data only, so logged-out visitors can use them. The link adds ?wcbp_status=open or ?wcbp_status=hiring to the directory address, so you can link to a filtered view directly.

Add your own filter (developers)

Hook the same BuddyPress argument filter and read your own query argument:

add_filter( 'bp_after_has_members_parse_args', function ( array $args ): array {
    if ( isset( $_GET['my_filter'] ) && 'mentors' === sanitize_key( wp_unslash( $_GET['my_filter'] ) ) ) {
        $args['include'] = get_users( array(
            'meta_key'   => 'open_to_mentor',
            'meta_value' => '1',
            'fields'     => 'ID',
        ) );
    }
    return $args;
} );

Tiered credit pricing

You can charge different credit costs to different members. Premium members can post jobs free, a discounted tier can pay half, and everyone else pays the full price.

Tiers come from a BuddyPress member type, a Paid Memberships Pro level, or a MemberPress membership. This works on sites that use only Paid Memberships Pro or MemberPress, without BuddyPress.

How the price is worked out

Each tier has a percentage multiplier applied to the base cost:

  • 100 is full price.
  • 50 is half price.
  • 0 is free.
  • A number above 100 marks the price up.

The final cost is the base cost times the multiplier, divided by 100, rounded, and never below 0.

The base cost is:

  • For a job post, the credit cost of the board the job is posted to. You can see it in the Credit Cost column of the Boards list.
  • For a featured upgrade, the Featured upgrade amount under Career Board > Settings > Credits.

The price is worked out for the job's author, not for the moderator who approves it.

If a member belongs to more than one listed tier, the lowest multiplier wins. If the base cost is 0, or the member is not in any listed tier, they pay the base cost.

Where to set the rules

There is no settings screen for tier pricing. Save the rules in the option wcbp_credit_cost_matrix, for example from a small plugin or with WP-CLI. The Integrations screen does not cover it.

The option is a list of rules per charge type (job_post or featured_upgrade), then per source, then per tier:

Source Tier key
bp_type BuddyPress member type slug
pmpro Paid Memberships Pro level ID (a number)
memberpress MemberPress membership ID (a number)
update_option( 'wcbp_credit_cost_matrix', array(
    'job_post' => array(
        'bp_type' => array(
            'mentor'  => 0,   // free
            'company' => 100, // full price
            'staff'   => 25,  // a quarter
        ),
        'pmpro' => array(
            2 => 0,   // level 2 posts free
            3 => 50,  // level 3 pays half
        ),
        'memberpress' => array(
            7 => 0,
        ),
    ),
    'featured_upgrade' => array(
        'pmpro' => array(
            2 => 0,   // level 2 features jobs free
        ),
    ),
) );

A member with PMPro level 3 (50) and the mentor member type (0) pays 0, because the lowest multiplier wins.

Example: free posting for paid members

  1. Set the board's credit cost to your full price, for example 10.
  2. Add a 0 multiplier for each paid level in the job_post rules.

Members in a listed tier post free. Everyone else pays 10.

Override the price in code (developers)

The wcbp_consumer_cost filter receives the cost, user ID, item ID, board ID and the charge type (job_post or featured_upgrade). The built-in tier rules run at priority 10, so a later priority overrides them:

add_filter( 'wcbp_consumer_cost', function ( $cost, $user_id, $item_id, $board_id, $consumer ) {
    if ( 'job_post' === $consumer && 42 === $user_id ) {
        return 10; // always full price for user 42
    }
    return $cost;
}, 20, 5 );

Group-scoped moderation

You can let BuddyPress group admins and moderators review jobs posted to their own group's board, without giving them site-wide moderator rights.

Normally only people with the moderate-jobs permission can approve or reject pending jobs, which on most sites means administrators. With this integration, a group admin or moderator can approve or reject a pending job that sits on their group's job board.

This works only while Group Job Boards is switched on under Career Board > Settings > Integrations.

What group admins can do

Action Allowed?
Approve a pending job on their group's board Yes
Reject a pending job on their group's board Yes
Resolve a flag on a job on their group's board Yes
Moderate a job on a different group's board No
Moderate a job that is not on any group's board No

The permission is checked per job, through the board the job sits on. An admin of group A cannot moderate jobs on group B.

What it does not add

The integration adds no new screen and no menu. It only allows the approve, reject and resolve-flag requests for those jobs. Group admins do not get the site-wide moderation permission.

Keep moderation site-wide only

Switch Group Job Boards off to remove the exemption. Only people with the site-wide moderate-jobs permission can then approve or reject jobs.

Profile tabs - My Jobs and My Career

You can show career information on each BuddyPress member profile. Employers get a My Jobs tab with their jobs and the applications they received. Candidates get a My Career tab with their applications, resume and saved jobs.

Profile Tabs is on by default. To turn it off, go to Career Board > Settings > Integrations, open the BuddyPress card, and switch off Profile Tabs. Turn it off if your BuddyPress theme already provides equivalent tabs.

Turning Profile Tabs off also turns off Application Notifications.

My Jobs (employers)

The tab shows on a profile when the member can post jobs and either has at least one job or is viewing their own profile.

Sub-tab Who sees it What it shows
Posted Anyone who can see the tab The member's jobs, with a count in the tab label
Applications The profile owner and site moderators Applications received across the owner's jobs

The profile owner sees their own count across all job statuses. Other visitors see a count of published jobs only.

The owner also gets a + Post a New Job button on both screens, linking to your Post a Job page.

My Career (candidates)

The tab shows on a profile when the member can apply for jobs and either is viewing their own profile or has a published resume.

Sub-tab Who sees it What it shows
Applications The profile owner and site moderators The member's submitted applications
Resume The owner always. Visitors only when a published resume exists The member's resume
Saved The profile owner and site moderators Jobs the member has bookmarked

Owners get action buttons: Browse Jobs on Applications, Edit Resume on Resume (opens the Resumes tab of the candidate dashboard), and Browse More Jobs on Saved. The owner's resume view includes private content. Visitors see the published resume only.

Who sees which tab

Tabs depend on what the member is allowed to do, not on their role name. Administrators and custom roles that can post jobs or apply for jobs get the matching tab. A plain candidate does not get My Jobs, and a plain employer does not get My Career.

The Applications, My Applications and Saved screens are private. Only the profile owner and site moderators see them. Candidates cannot see each other's applications, and employers cannot see a candidate's application list.

Styling

The tabs use your theme's BuddyPress layout with the plugin's own job and resume styles. No theme changes are needed.

Migration

Import from WP Job Manager and CSV.

Migration and CSV import

You can move jobs into Career Board from a spreadsheet, and re-run the same file later to update them instead of creating duplicates. Pro adds a CSV importer card to the Import screen, next to the built-in WP Job Manager cards.

Rows import as Pending unless the status column says publish or draft.

CSV Import

Finding the Import Screen

Go to Career Board → Import and look for the CSV → Jobs card (marked Pro). Only users who are allowed to manage Career Board settings see it.

Download the Sample File

Click Download Sample CSV to get a template with two example rows. Use it as a starting point for your data.

CSV Column Reference

Required

Column Description
title Job title - the only required column

Content

Column Description
description Full job description (HTML allowed)
status pending, publish, or draft. Any other value, or an empty cell, becomes pending.
deadline Application deadline. Any date format PHP can read; it is saved as YYYY-MM-DD.

Salary

Column Accepted values
salary_min Integer (e.g. 80000)
salary_max Integer (e.g. 120000)
salary_currency Any currency code in the plugin's currency catalog (e.g. USD, EUR, GBP, CAD, AUD, INR, SGD). Codes are matched case-insensitively.
salary_type yearly, monthly, or hourly

If salary_min is greater than salary_max, the importer swaps them automatically and records a warning.

Flags

Column Accepted values
remote yes, 1 or true turns it on. Any other value turns it off.
featured yes, 1 or true turns it on. Any other value turns it off.

Company

Column Description
company Company name text
company_id WordPress post ID of an existing company post

Application

Column Description
apply_url External application URL
apply_email Application contact email

Taxonomies

Separate multiple values with commas or pipes. Terms are created automatically if they do not exist.

Column Taxonomy
categories Job category
job_types Job type (e.g. `Full-time
locations Location
experience Experience level
tags Job tags

Geo and Board

Column Description
lat Latitude (decimal)
lng Longitude (decimal)
board_id WordPress post ID of the target job board (Multi-Board)

Matching

Column Description
external_id Optional stable ID from your source system. Used to match rows on re-import. It is not treated as a custom field.

Custom Fields

Add a field key from the Field Builder as a column header to fill that custom field on each imported job. Columns that match no field key are ignored.

Running the Import

  1. Select your CSV file using the file picker
  2. Click Upload & Import
  3. A results summary shows counts for Imported, Updated, Skipped, and Warnings. Per-row errors are listed under a "View row errors" toggle.
  4. Use the Review pending jobs link to review the Pending listings before publishing

Imported jobs are authored by the user who runs the import. On a re-import, an empty cell keeps the job's existing value for every column except title, description and status. An empty description clears the description, and an empty status sets the job back to Pending.

Idempotent Re-Imports

Re-importing a CSV never creates duplicate jobs. Each row is matched against jobs already imported by:

  • An external_id column, if your CSV provides one (recommended - ties each row to a stable ID from your source system), or
  • A natural key derived from the row's title, company, and board when no external_id is given.

A row that matches an existing import updates that job in place (title, description, status, and the fields with a value in the row) and counts as Updated. A row with no match creates a new job and counts as Imported. This means you can re-run the same file - or a refreshed export from your source system - on a schedule without piling up duplicate listings.

Geocoding and candidate alerts

Imported jobs are geocoded in the background, the same way a job posted through the frontend is. The import never waits on a geocoding service, so pins can appear a few minutes after a large import. See Job Map.

Candidates with a matching instant job alert are told when a job becomes public, not when it is imported. A row with status set to publish alerts them as it is imported. A row left pending alerts them when you approve it. Each job alerts once. A bulk import does not send the pending-review email or post to the activity stream that a new frontend submission would.

Jobs migrated from WP Job Manager by the Free importer do not alert candidates by default. Developers can allow it with the wcbp_alerts_notify_on_import filter (return true). CSV imports are not affected by that filter.

Error Handling

Condition Result
File not found or unreadable Import stops with an error message - no rows processed
Empty file or no header row Import stops with an error message - no rows processed
Missing title column Import stops with an error message - no rows processed
Row has wrong column count Row skipped, error logged in summary
Empty title on a row Row skipped, error logged in summary
Invalid currency or salary type Field skipped for that row
Invalid date Field skipped for that row
salary_min greater than salary_max Values swapped automatically, counted as a warning

WP Job Manager migration

You can move a WP Job Manager site onto Career Board from the same Career Board → Import screen. The cards are:

  • WP Job Manager → Jobs - copies job_listing posts to Career Board jobs with title, description, author, publish date, salary, deadline, categories, job types, tags and company pages. The Free plugin provides it, so you do not need Pro.
  • WP Job Manager Applications → Applications - moves applications onto the imported jobs. Import the jobs first. No emails are sent.
  • WP Job Manager Resumes → Resumes - copies resumes. It is unlocked by Pro.

Each migration is safe to run more than once. Records that were already imported are skipped, and each card shows how many were found and how many are already imported.

Pro Blocks

Every Pro block, its attributes, and example uses.

Pro blocks reference

You can add Pro features to any page with blocks: a job map, resume search, a candidate directory, credit balance, job alerts and more. This page lists each Pro block, the settings it has and where to put it.

All Pro blocks are in the Widgets category. Most of them are in the block inserter. Four are not, because Career Board places them for you:

  • Application Kanban - on the Hiring Pipeline page.
  • Credit Balance - as the Credits tab of the Employer Dashboard.
  • Resume Builder - inside the Candidate Dashboard.
  • My Applications - not in the inserter. Add it with its shortcode.

Shortcodes

Every Pro block also has a shortcode, so you can use it in a page builder or the classic editor. Use the block attributes below as the shortcode attributes, for example [wcbp_resume_archive perPage="12"].

Block Shortcode
AI Chat Search [wcbp_ai_chat_search]
Application Kanban [wcbp_application_kanban]
Credit Balance [wcbp_credit_balance]
Featured Candidates [wcbp_featured_candidates]
Featured Companies [wcbp_featured_companies]
Job Alerts [wcbp_job_alerts]
Job Map [wcbp_job_map]
My Applications [wcbp_my_applications]
Open to Work [wcbp_open_to_work]
Find Resumes [wcbp_resume_archive]
Resume Builder [wcbp_resume_builder]
Resume Form (Single-Page) [wcbp_resume_form]
Resume Form (Quick Profile) [wcbp_resume_form_simple]
Resume Map [wcbp_resume_map]
Resume Search Hero [wcbp_resume_search_hero]
Resume Single [wcbp_resume_single]

The experience filter of the Resume Search Hero can be switched off only in the block editor.

Where to add each block

Block Recommended page
AI Chat Search Jobs page, in place of or above the standard Job Search block
Application Kanban The Hiring Pipeline page (created for you)
Credit Balance Shown in the Employer Dashboard Credits tab
Featured Candidates Homepage or company page sidebar
Featured Companies Homepage or jobs page sidebar
Job Alerts Jobs page, below or beside the Job Listings block
Job Map Jobs page, alongside Job Listings and Job Filters
My Applications A candidate page, through its shortcode
Open to Work Homepage sidebar or employer-facing pages
Find Resumes The Find Candidates page (created for you)
Resume Builder Shown inside the Candidate Dashboard
Resume Form (Single-Page) A dedicated resume page, for a long one-screen form instead of the section-by-section builder
Resume Form (Quick Profile) Sidebars, modals, partner pages and onboarding flows
Resume Map Find Candidates page, alongside Find Resumes
Resume Search Hero Find Candidates page, above Find Resumes
Resume Single Applied to single resume pages automatically

Add a Pro block

  1. Open a page in the WordPress editor.
  2. Click + to add a block.
  3. Search for the block name, for example "Job Map".
  4. Click it to insert it.

Who sees the candidate blocks

Find Resumes, Resume Search Hero, Resume Map, Featured Candidates and Open to Work follow the Candidate directory visibility setting under Career Board > Settings > Resumes. If a visitor is not allowed to browse candidates, these blocks show nothing.

Block details


You can let signed-in members describe the job they want in their own words, such as "remote product manager role with equity", and get up to 10 matching jobs.

Attribute Type Default Description
placeholder string "Describe your ideal job..." Input placeholder text

Before it works you need an OpenAI or Ollama provider set for matching under Career Board > Settings > AI Settings. Until a provider is set, administrators see a notice and other visitors see nothing. Visitors who are not signed in cannot run a search. See AI features.


Application Kanban (wcb/application-kanban)

You can let employers move applicants between hiring stages by dragging cards on a board.

Attribute Type Default Description
jobId integer 0 The job whose pipeline the board shows

The board opens for one job. Employers open it from the Pipeline button on their dashboard, which adds ?job=ID to the Hiring Pipeline page. With no job set, the block shows a link back to the dashboard. Only the job's owner and administrators can see the board. See Application Pipeline.


Credit Balance (wcb/credit-balance)

You can show employers their credit balance, a Buy Credits button, purchases awaiting payment, receipts and their transaction history. On the Employer Dashboard this block is the Credits tab.

Attribute Type Default Description
showHistory boolean true Show or hide the transaction history

It shows the signed-in user's own balance and shows nothing to signed-out visitors. What can be bought comes from your Credits settings. If nothing can be bought, the block says so instead of showing a Buy button. See Native Buy Credits checkout.


You can highlight candidates you have marked as featured in a sidebar list.

Attribute Type Default Description
count integer 5 Number of candidates to show
title string "Featured Candidates" Heading above the list
showViewAll boolean true Show a "View all" link
viewAllUrl string Find Candidates page Where the "View all" link goes

It lists the newest resumes that are marked featured and set to public. Each row shows the photo, name, the job title from the first experience entry, and up to 3 skills. Visitors see nothing when there are no featured candidates. Administrators see a short message.


You can show featured companies with their open positions in a sidebar list.

Attribute Type Default Description
count integer 5 Number of companies to show
title string "Featured Companies" Heading above the list
showViewAll boolean true Show a "View all" link
viewAllUrl string empty Where the "View all" link goes. The link shows only when this is set.

It lists companies marked featured, newest first. If no company is marked featured, it lists the newest companies instead. Each row shows the logo, name and number of open positions.


Job Alerts (wcb/job-alerts)

You can let signed-in members save the job search they are looking at as an alert and choose how often to hear about new matches.

This block has no attributes.

It uses the search on the same page (Job Listings and Job Filters). When a member picks Instant, Daily or Weekly and clicks Subscribe, the alert saves the keyword, category, job type, location, salary range and remote filter they had set. The block lists their active alerts, and they can delete each one. It shows nothing to signed-out visitors. See Job Alerts.


Job Map (wcb/job-map)

You can show job locations on a map that narrows to the jobs matching the Job Listings search on the same page.

Attribute Type Default Description
height integer 480 Map height in pixels

Jobs need a location so they can be geocoded. Geocoding runs in the background after a job is saved, so a new pin can take a few minutes. Jobs without coordinates are not shown. The map always uses OpenStreetMap tiles. The Google or Mapbox setting changes only the geocoding service. The block includes a place search, a radius picker and Use my location. See Job Map.


My Applications (wcb/my-applications)

You can show a member their submitted applications as a table with Job, Status and Submitted columns. On narrow screens it becomes a list of cards.

Set employerId to show an employer the applications received for their jobs, with an Applicant column.

Attribute Type Default Description
authorId integer 0 Show another user's applications. 0 means the signed-in user. Only administrators can view someone else's.
employerId integer 0 Show the applications received for this employer's jobs. Only that employer and administrators can see them.
perPage integer 20 Applications to show, up to 100

The block shows the newest applications up to perPage. The Status column always shows a badge, and an application with no status shows as "Submitted".


Open to Work (wcb/open-to-work)

You can show candidates who are open to work in a sidebar list.

Each row shows:

  • The photo from the resume, or an initial when there is none.
  • The name.
  • The job title from the first experience entry.
  • The location from the resume, or from the first experience entry when the resume has none.
  • Years of experience, counted from the earliest experience start date.
  • Up to 3 skills.
Attribute Type Default Description
count integer 5 Number of candidates to show
title string "Open to Work" Heading above the list
showViewAll boolean true Show a "View all" link
viewAllUrl string Find Candidates page Where the "View all" link goes

Only public resumes of candidates who turned on Open to new opportunities are listed. The block picks from the most recently saved ones and shuffles them on each load.


Find Resumes (wcb/resume-archive)

You can give employers a searchable, paged directory of public candidate resumes.

Attribute Type Default Description
perPage integer 12 Resumes per page
authorId integer 0 Show only one user's resumes. 0 shows everyone.

Each card shows the photo, name, job title, skills and location. The keyword search matches every word against the resume title, headline, summary, location or a skill. The sidebar filters by skill (the 30 most used), experience level, location and open to work. Results sort newest or oldest first. Each change updates the page address without a full reload, so a filtered view can be shared as a link. When a Resume Search Hero is on the same page, the sidebar filters are hidden.

The Find Candidates page has this block and the Resume Search Hero already on it.


Resume Builder (wcb/resume-builder)

You can let candidates build and edit their resumes section by section, including education, experience, skills and more, with a Public or Private switch.

This block has no attributes.

It needs a signed-in candidate. It opens the resume from the ?resume_id= address, or the candidate's own resume when there is none. The Candidate Dashboard already opens it for you. See Resume Builder setup.


Resume Form, Single-Page (wcb/resume-form)

You can give candidates one long form with every section open, instead of the section-by-section builder. It saves to the same resume data.

Attribute Type Default Description
compact boolean false Use a tighter, narrower layout

It needs a signed-in candidate. See Single-Page Resume Form.


Resume Form, Quick Profile (wcb/resume-form-simple)

You can give candidates a short form for the essentials: headline, summary, top skills, location, open-to-work status and a photo. It fits sidebars, modals, partner pages and onboarding flows.

Attribute Type Default Description
showPhotoField boolean true Show the photo upload field
compact boolean false Use a tighter, narrower layout

It needs a signed-in candidate. It saves to the candidate's resume, so the headline, location, skills and open-to-work status feed the Open to Work and Featured Candidates blocks. See Quick Resume Form.


Resume Map (wcb/resume-map)

You can give employers a map of where candidates are. Clicking a pin opens a popup with a link to the candidate's resume.

Attribute Type Default Description
height integer 480 Map height in pixels

Only public resumes with coordinates get a pin. Pins are placed at city level (rounded to about 1 km), never at a street address. The map shows the newest 500 pins. When there are more, a line under the map reads "Showing the newest 500 of N candidates. Use the candidate search to find the rest." It includes a radius search.


Resume Search Hero (wcb/resume-search-hero)

You can put a full-width candidate search form above the directory. It sends the visitor to the Find Candidates page with the search applied.

Attribute Type Default Description
layout string horizontal horizontal or vertical
placeholder string "Search candidates..." Search input placeholder
buttonLabel string "Search" Search button label
showSkillFilter boolean true Show the skill dropdown
showExperienceFilter boolean true Show the experience dropdown
showOpenToWorkFilter boolean false Show the open-to-work option

Resume Single (wcb/resume-single)

You can show a candidate's full resume on its own page. Career Board applies this block to single resume pages for you, so you usually do not add it yourself.

Attribute Type Default Description
resumeId integer 0 Show a specific resume. 0 uses the resume page being viewed.

The block supports wide and full alignment. A private resume shows "This resume is private." unless the viewer is its owner or is allowed to view resumes.

FAQ

Quick answers for site owners, employers and candidates.

FAQ for site owners

Do I need an active license for Pro to work?

No. The license only controls automatic updates and support. Every Pro feature on your website keeps working with no license, an expired license or an invalid key. The one exception is the companion mobile app connection, which stays off until the license is valid. See License activation.

Why does Pro say it needs a newer Free plugin?

Pro needs a minimum version of WP Career Board (Free). If Free is older, Pro turns itself off when you activate it and tells you to update Free first. Update both together.

How are credits charged and refunded?

When an employer submits a job on a board that has a credit cost, the credits are held straight away. If the balance is too short, the request is refused and nothing changes. The hold becomes a charge when the job goes live. A job that is still waiting for approval keeps its hold. If it is rejected, or trashed or deleted before it goes live, the hold is released and the credits return. A job that you approve while its author is short of credits stays pending and goes live by itself after the author buys or is granted credits. Once a job is live, moving it to the trash does not return credits on its own. Use a manual adjustment for that. See Credit system overview and Manual adjustments and refunds.

Is posting free by default?

Yes. A board's Credit cost per job defaults to 0. Credits only apply once you set a cost above 0 on a board. See Multi-board.

What happens if an employer has too few credits?

The job is not published. Employers can buy credits in the Credits tab of their dashboard. If you set a cost on a board before you have set up any way to sell credits, employers are turned away, and a warning appears on Career Board screens. See Native checkout.

Does the job map need an API key?

No. The default map provider is Leaflet with OpenStreetMap, which needs no key. Google Maps and Mapbox need your own API key. See Job map.

How does radius search work?

A visitor picks a place and a radius in kilometres (1 to 500, default 25). Pro turns the place into coordinates and limits the job search to a square box around it, so totals and paging stay correct. Jobs with no coordinates never match. The corners of the box reach a little farther than the radius. See Job map.

When do jobs get their map coordinates?

In the background, not when the employer clicks Save. Saving a job or resume queues a lookup and the pin appears when it finishes. Jobs whose location is only "Remote" or a similar word such as "Hybrid" get no pin. See Troubleshooting: no map pins.

How do job alerts work for people without an account?

A visitor enters an email address and search. Pro sends a confirmation email, and the alert only starts after they click the link (double opt-in). Every alert email carries an unsubscribe link. Guest alerts are on by default, capped at 10 alerts per email address, and you can turn them off or change the cap under Settings > Job Alerts, where you can also see every saved alert. See Job alerts.

Where do I see all the Pro settings?

See the Pro settings reference.

FAQ for employers

Why is an applicant not on my pipeline board?

Applications that are withdrawn, position closed or job removed leave the board, and you cannot move them. Cards for a job you close leave the board, and come back when you reopen the job. Only applications for that one job show, so check the job ID in the address (?job=). See Application pipeline.

Where is the Pipeline button?

It sits on each job row of your employer dashboard and opens the Hiring Pipeline page for that job. It only shows when the site has a Hiring Pipeline page. If it is missing, ask the site owner to see Troubleshooting: Pipeline button missing.

Does moving a card change the application status?

Only for stages with an outcome. Moving a card to a Hired or Rejected stage sets that status. Moving it out sets the status back to Reviewing. Other stages are for your own tracking. See Application pipeline.

How do I buy credits?

Open the Credits tab of your employer dashboard and pick a pack or enter an amount. Your receipt is emailed after the payment is confirmed. See Native checkout and Checkout, receipts and emails.

Will I get my credits back if a job is rejected?

Yes, while the job has not yet gone live. Credits held for a pending job return when it is rejected or removed. Once a job is live, ask the site owner for a manual adjustment. See Manual adjustments and refunds.

The site owner sets it (10 credits by default). Use Feature on a job in My Jobs, or the checkbox on the job form. A featured job lists first for a set number of days. The price shows when credits are on. See Featured upgrade.

Can I add my own questions to a job form?

Yes, if the site owner added an Application questions group in the Field Builder. Those questions appear on the apply form, and required ones must be answered before the application is sent. See Field Builder.

FAQ for candidates

What does my resume PDF include?

Your name, email, phone and location, your headline (in place of the resume title) and summary, then each section you filled in: work experience, education, school, certifications, skills, languages and portfolio. You need to be signed in to download it. See Print and download a resume.

How do I print my resume?

Open your resume page and click Print. The browser's print dialog opens with a print layout that hides the site chrome. A short resume prints on one page. If it looks wrong, see Troubleshooting: resume printing.

Who can see my resume?

That is up to you and the site. You choose whether each resume is public. The site owner decides who may browse the candidate directory and who may open a single resume profile (anyone, logged-in members, or approved employers). See Find Candidates.

Can I get job alerts without an account?

Yes, when the site allows it. Enter your email and search, then click the link in the confirmation email. Alerts do not start until you confirm. Each email has an unsubscribe link. See Job alerts.

How many alerts can I have?

Up to 10 by default. The site owner can change the limit under Settings > Job Alerts.

How often will I get emails?

Each alert is instant, daily or weekly. Instant alerts go out when a matching job is published. Daily digests are sent at 8:00 UTC and weekly digests on Mondays at 8:00 UTC. You can turn off the job alert email under Email Notifications in your dashboard account section, or use the unsubscribe link in any alert email.

Can I search for jobs near me?

Yes, on sites that use the job map. Pick a place and a radius in kilometres. See Job map.

Why did I stop getting bell notifications for a job?

If the job was removed or closed, the notification says so in its own sentence and the link is shown as plain text, because the page no longer exists. See Notifications.

Troubleshooting

Fixes for the problems people hit most often.

Troubleshooting: license and updates

The License tab shows Inactive, Expired or Invalid

Cause. The license only controls updates, so the status does not affect any feature. It is inactive when the key was never activated on this site, expired when the period ended, and invalid when the key does not match a license.

Fix.

  1. Go to Career Board > Settings > License and check the key against the one in your purchase email or your account at wbcomdesigns.com.
  2. Paste the key again and click the activate button.
  3. If the status is No activations left, deactivate the key on a site you no longer use, then activate it here.
  4. If it is Inactive on this site, activate the key on this site. If it is Item mismatch, the key belongs to another product. Use the key for WP Career Board Pro.

See License activation.

No update shows for Pro

Cause. Updates come from wbcomdesigns.com and need an active license and a connection from your server to that site.

Fix. Activate the license, then check that your host allows outbound HTTPS requests to wbcomdesigns.com. Update Free and Pro together.

Pro deactivated itself on activation

Cause. Pro checks Free on activation. It turns itself off, with an error message, when Free is missing or older than the version Pro needs.

Fix. Install or update WP Career Board (Free), then activate Pro again. The error message names the version Pro needs.

The mobile app will not connect

Cause. The companion app connection is the one feature that needs a valid license.

Fix. Activate the license, then retry.

Troubleshooting: credits and payments

An employer paid but the job is still pending

Cause. A job that a moderator approved but that needed credits its author did not have stays pending instead of going live for free.

Fix. Credits added by a purchase, a top-up or a manual adjustment publish the author's waiting jobs automatically, oldest first, up to 20 at a time, stopping at the first job the balance cannot cover. If the job is still pending, check the Transactions card under Career Board > Settings > Analytics to see whether a Stripe or PayPal purchase arrived, and check the payment webhook. Purchases made through WooCommerce, PMPro or MemberPress do not appear in that card. See Native checkout and Direct payment gateways.

Employers are turned away when posting

Cause. A board has a credit cost above 0 but nothing can sell credits, so no employer can pay. Career Board screens show a warning.

Fix. Turn on Stripe or PayPal and add a credit pack, or map a WooCommerce, PMPro or MemberPress product. Or set the board's Credit cost per job back to 0.

Credits were not returned for a removed job

Cause. Credits held for a job return only while the job has not gone live yet. A live job that is trashed is not refunded automatically.

Fix. Add the credits back with a manual adjustment. See Manual adjustments and refunds.

Troubleshooting: map pins and radius search

Coordinates are looked up in the background after a job or resume is saved, so a pin never appears at the moment of saving. The job map shows jobs that have coordinates. See Job map.

A job has no pin on the map

Cause. One of these:

  • The job has no Location term, or its only location is a word such as "Remote", "Anywhere", "Hybrid" or "Work from home". These jobs are skipped on purpose.
  • The background lookup has not run yet. It runs through Action Scheduler when it is installed, or WP-Cron otherwise, so a site with WP-Cron disabled and no other runner never looks anything up.
  • The lookup failed. A failed lookup leaves the job without coordinates and shows no error.
  • The map provider is Google Maps or Mapbox and its API key is empty or wrong.

Fix.

  1. Edit the job and check it has a real place in Location.
  2. Make sure your scheduled tasks run (a real cron hitting wp-cron.php, or Action Scheduler with a runner).
  3. Under Settings > Integrations, check the provider and key. Use Leaflet / OpenStreetMap to test, since it needs no key.
  4. Save the job again. Saving queues a new lookup for any job that has no coordinates yet. A job that already has coordinates is looked up again only when its location changes.

Old jobs are missing pins after an upgrade

Cause. When you upgrade from an older Pro version, a background sweep looks up published jobs and resumes that have no coordinates, 25 at a time, with a pause of about 1.1 seconds between lookups. The pause keeps the sweep inside the free OpenStreetMap limit.

Fix. Wait. A large board can take a while. On Google or Mapbox you can shorten the pause with the wcbp_geocode_throttle_us filter (microseconds, default 1100000).

The place search box says "Too many location searches"

Cause. Each visitor IP address can run 30 new place searches per hour. Searches for text that was looked up recently are answered from a saved result and do not count.

Fix. Wait and try again, or raise the limit with the wcbp_geocode_rate_limit filter. Return 0 to remove the limit.

The place search finds nothing

Cause. The provider found no place for that text, or the lookup failed. The failure is remembered for an hour, so the same text fails the same way until then.

Fix. Try a city name or a fuller address. On Google or Mapbox, check that the Geocoding API is enabled on your key.

Radius search returns no jobs

Cause. Radius search only matches jobs that already have coordinates. The radius is in kilometres, from 1 to 500, and defaults to 25.

Fix. Check that the jobs you expect have pins on the map, then widen the radius.

Troubleshooting: hiring pipeline

The Pipeline button is missing on my job rows

Cause. The button only shows when the site has a Hiring Pipeline page. Sites upgraded from an older version get the page created after the upgrade. If that did not happen, or someone deleted the page, the button stays hidden.

Fix.

  1. Go to Career Board > Settings > Pages and check Hiring Pipeline Page.
  2. If it is empty, use Create Missing Pages. This adopts an existing page that already holds the Application Kanban block.
  3. Or add a page with the Application Kanban block yourself and choose it in that setting.

The page slug is hiring-pipeline. See Hiring Pipeline page.

The pipeline page says "You don't have access to this job's pipeline"

Cause. Only the job's author, moderators and administrators can open a job's board, and only if they can view applications. This is a permission message, not a load error.

Fix. Sign in as the job's author, or as a moderator or administrator.

The pipeline page asks me to use the Pipeline button

Cause. The page was opened without a job in the address.

Fix. Open it from the Pipeline button on a job row, or add ?job=123 with the job's ID.

An application is not on the board

Cause. Withdrawn, position closed and job removed applications leave the board. Applications also show only on the board of their own job.

Fix. Check the application's status in the applications list. If the job was closed by mistake, reopen it and the cards return.

Old cards are in the wrong column after an upgrade

Cause. After an upgrade, a background sweep lines up existing cards with their application status, 200 applications at a time. It starts a minute after the upgrade.

Fix. Wait for it to finish. Make sure scheduled tasks run on your site.

A card will not move

Cause. The application is closed (withdrawn, position closed or job removed), or the target stage belongs to a different board.

Fix. The board shows "That application could not be moved. It has been put back - please try again." Check the application's status. Reopen the job if it was closed, and move the card only to a stage on the same board.

Troubleshooting: resume printing and PDF

The printed resume looks wrong in my theme

Cause. The print layout applies to the single resume page (/resume/...). It does not apply when the resume block sits on a custom page or inside a page-builder layout, where the theme's own wrappers, padding and print styles take over. A cache or minify plugin serving an older stylesheet gives the same symptom.

Fix.

  1. Print from the resume's own page, not from a page you built with the block.
  2. Clear your page cache and the minified CSS, then reload.
  3. In the print dialog, turn on Background graphics if skill bars and dots are missing.
  4. If your theme ships its own single-wcb_resume.php template, it replaces the one from Pro. Remove it or copy the Pro template's structure.

The printed page uses a 12 mm margin that Pro adds after the theme's stylesheets, so a theme's own page margin does not override it. See Print and download a resume.

The Download PDF button asks me to sign in

Cause. Only signed-in people can download a resume PDF.

Fix. Sign in. The candidate, anyone allowed to read that resume and site managers can download it.

The PDF is missing a section

Cause. The PDF only includes sections with entries: summary, work experience, education, school, certifications, skills, languages and portfolio.

Fix. Fill in the section on the resume and download again.

The PDF fails to generate

Cause. The PDF library bundled with Pro is missing or blocked, for example from an incomplete upload.

Fix. Reinstall the Pro plugin from a fresh zip. To use another PDF engine, return a callable from the wcbp_resume_pdf_renderer filter.

Troubleshooting: PWA and push notifications

The installable app works on a site that runs at the domain root, for example https://example.com. These steps assume that setup.

The browser does not offer to install the app

Cause. One of these:

  • The site is not on HTTPS.
  • You are not on a page that carries the manifest. It is linked only on job archive pages, single job pages, and the jobs archive, employer dashboard and candidate dashboard pages you set under Settings > Pages.
  • The site has no Site Icon, so the manifest has no icons.
  • The site runs in a subfolder. The manifest (/wcb-manifest.json) and service worker (/wcb-service-worker.js) are only served at the domain root.

Fix.

  1. Serve the site over HTTPS.
  2. Upload a Site Icon under Settings > General. The manifest uses the 192 and 512 pixel versions.
  3. Open one of the pages listed above and reload.
  4. Open https://your-site.com/wcb-manifest.json in the browser. It should show JSON. If it shows a 404 page, check for a server rule or cache that intercepts the address.

See PWA.

The installed app shows the wrong color

Cause. The manifest takes its color from the Brand colour.

Fix. Change the color under Career Board > Settings > Brand, then open /wcb-manifest.json and check that theme_color shows the new value.

Offline pages do not load

Cause. The service worker only handles /jobs/, /companies/ and /candidates/, and only pages that were visited before are cached. If your job archive uses a different slug, its pages are not cached.

Fix. Visit the page once while online. Use the standard /jobs/ slug if you need offline viewing.

Push notifications do not arrive

Cause. Push is sent only to the native companion app. The website and the installed PWA do not send browser push. The member's phone must also be registered.

Fix.

  1. Sign in to the companion app on the phone. The app registers its push token with POST /wcb/v1/push/register-device.
  2. Check the phone allows notifications for the app.
  3. Push is sent in the background, so scheduled tasks must run (Action Scheduler or WP-Cron).
  4. The mobile app connection needs a valid license. See Troubleshooting: license and updates.
  5. A device that the push service reports as no longer registered is removed. Sign in to the app again to register it.

A push is sent for the same events that add a row to the notification bell. See Notifications.

Developer Guide

Hooks reference, REST API, and extending Free.

Developer Guide - Overview

WP Career Board Pro is built as an extension of WP Career Board (Free), not a fork. Pro extends Free through Free's hooks. The runtime guard (wcbp_free_active()) makes sure Pro degrades gracefully when Free is deactivated.

Use this guide when:

  • You're writing an addon that consumes Pro features (resume builder, application kanban, AI hiring tools, credit SDK).
  • You want to see how Pro and Free work together.
  • You're writing a custom credit adapter or payment gateway.

For Free-side dev surface (the hooks, REST endpoints, and CLI commands every site is built on), start with the Free developer guide (see the WP Career Board docs).

Free/Pro coupling contract

Pro extends Free through four rules. The check script (bin/architecture-checks.sh) enforces A1-A3; A4 is enforced in code review:

ID Title What it guards
A1 Lockstep version Pro and Free keep the same version number in their plugin headers, so a half-updated install shows up in the check.
A2 Dependency guard Pro defines wcbp_free_active() and uses it to gate boot. Deactivating Free does not fatal Pro.
A3 REST namespace shared, paths disjoint Both register under wcb/v1; Free and Pro routes never collide.
A4 No source modification Pro hooks Free via documented filters only. Never patches Free's classes.

If you're shipping your own Pro-side addon, follow the same invariants - they're the operational contract that lets Pro and the addon coexist without one breaking the other.

Architecture at a glance

Layer Where Purpose
Blocks blocks/<name>/render.php + view.js Pro blocks such as kanban, alerts, resume builder and search, credit balance, AI chat search, and job and resume maps
REST API api/endpoints/class-*-endpoint.php Pro routes under wcb/v1/* extending Free's WCB\Api\RestController (via Pro's WCB\Pro\Api\ProRestController); see the REST API reference
Modules modules/<area>/ Pro features, one folder each, for example ai, alerts, boards, credits, fields, maps, pipeline, push, resume
SDK libs/wbcom-credits-sdk/ Wbcom Credits SDK (bundled in libs/, not vendor/, so it ships in release zips). Adapters: WooCommerce, WC Subscriptions, WC Memberships, PMPro, MemberPress. Gateways: Stripe, PayPal
Core core/class-*.php Lifecycle: ProInstall, ProPlugin, License, FreeCoordination

Contents

Doc What's inside
02-extending-free.md The canonical Pro-extends-Free contract - dependency guard, REST sharing, lockstep
03-hooks-reference.md Pro's own actions and filters
04-credits-sdk.md The Wbcom Credits SDK - registration, consumers, adapters, gateways, ledger
05-ai-providers.md The AI hiring tools - REST endpoints, provider drivers, and how to add your own provider
06-rest-api-reference.md The Pro REST routes: method, who may call it, parameters
07-shortcodes.md The Pro shortcodes and their attributes

Working against Pro from a third-party plugin

To build an addon that depends on Pro:

  1. Declare Pro as a Requires Plugins: header in your main file.
  2. Gate your runtime hooks behind a defined( 'WCBP_VERSION' ) check.
  3. Verify your minimum Pro version with version_compare() against WCBP_VERSION.
  4. Hook into Pro's documented actions/filters from 03-hooks-reference.md. Never reach into internal classes - those aren't part of the public contract.

Pro's bin/architecture-checks.sh (run with composer arch-checks) is a working example of a check script you can copy for your own addon.

Extending Free - The Canonical Pro Contract

Use this page to build an addon that extends WP Career Board Free the way Pro does, without forking it. Every pattern here is something a third-party addon can copy.

The four invariants

Pro's check script (composer arch-checks) enforces A1 to A3. Your addon should aim for the same:

A1 - Lockstep version

Pro's plugin header version matches Free's, and the check script fails on drift. Why: shipping one updated and the other not means a customer has a half-built release, and cross-plugin hook signatures go out of sync. Pro also refuses to boot against a Free older than its minimum supported version.

For an addon, your equivalent is "what's the minimum Free version I work against?" Declare it as a constant (MYADDON_MIN_WCB = '1.0.0'), check at boot:

if ( ! defined( 'WCB_VERSION' )
     || version_compare( WCB_VERSION, MYADDON_MIN_WCB, '<' ) ) {
    add_action( 'admin_notices', 'myaddon_min_wcb_notice' );
    return;
}

A2 - Dependency guard

Pro defines wcbp_free_active() and uses it inside the boot path:

function wcbp_free_active(): bool {
    return defined( 'WCB_VERSION' );
}

if ( ! wcbp_free_active() ) {
    add_action( 'admin_notices', 'wcbp_missing_free_notice' );
    return;
}

The guard runs on plugins_loaded at priority 20. Free loads at priority 10, so by the time Pro's check fires Free has already booted. If a customer deactivates Free via WP-CLI (which bypasses the Requires Plugins: header), Pro detects it and gracefully skips its hooks instead of fataling.

A3 - REST namespace shared, paths disjoint

Both plugins register under the same wcb/v1 namespace - that's intentional so the API surface stays cohesive to consumers. Disjointness is what matters:

Free:  /jobs, /jobs/{id}, /candidates/{id}, /candidates/{id}/applications ...
Pro:   /resumes, /boards/{id}, /applications/{id}/stage, /alerts ...

The check script compares the route lists of both plugins and fails if a path appears in both. If you're adding routes from an addon, pick a unique sub-path and document it.

A4 - No source modification

Pro does not patch Free's classes. All extension goes through documented filters and actions. The contract is one-way: Free exposes the hooks; Pro and other addons consume them.

Pro REST routes

Pro registers its routes under the shared wcb/v1 namespace, one endpoint class per group in api/endpoints/ (these classes extend WCB\Pro\Api\ProRestController). The setup wizard routes are registered by the Pro setup wizard. License status never gates these routes: the license drives automatic updates only. The full list, with who may call each route and its parameters, is in the Pro REST API reference.

Mobile/companion-app push routes

POST and DELETE /wcb/v1/push/register-device back the native (Expo) push feature for the mobile app. Both require a logged-in member (is_logged_in()). Like the notification bell, a member's own device registration keeps working regardless of license status.

// POST /wcb/v1/push/register-device
// Body: { "expo_push_token": "ExponentPushToken[xxxxxxxx]", "platform": "ios"|"android", "device_name": "..." }
// -> 201 { "registered": true }  |  400 wcb_invalid_push_token  |  500 wcb_push_register_failed

// DELETE /wcb/v1/push/register-device
// Body: { "expo_push_token": "ExponentPushToken[xxxxxxxx]" }
// -> 200 { "unregistered": true }

The token is validated against Expo's ExponentPushToken[...] / ExpoPushToken[...] shape before it's stored. PushModule does not author its own notifications or keep a separate queue - it listens on the existing wcb_notification_created action and fans each message out to the caller's registered devices via the shared AsyncScheduler. See 03-hooks-reference.md.

The SDK's own checkout/webhook/refund routes (a separate wbcom-credits/v1 namespace, not wcb/v1) are documented in 04-credits-sdk.md.

How Pro consumes Free's hooks

The cleanest examples in the codebase:

Returning Pro's status to Free's gate filters

Free fires apply_filters( 'wcb_pro_active', false ) to check whether Pro is running. Pro registers:

// In core/class-free-coordination.php
add_filter( 'wcb_pro_active', '__return_true' );

Pro registers all of these in core/class-free-coordination.php: wcb_pro_active, wcb_pro_licensed, wcb_pro_version, wcb_pro_ai_enabled, wcb_pro_alerts_enabled, wcb_pro_resumes_enabled, and wcb_pro_settings_saved_notice. Each returns a value Pro alone can authoritatively answer.

Reading credit balances and pricing from the SDK

The credit system is owned by the Wbcom Credits SDK, not by a Free placeholder filter. Pro's blocks and endpoints read the balance directly:

$balance = \Wbcom\Credits\Credits::get_balance( 'wp-career-board', $user_id );
$url     = \Wbcom\Credits\Credits::get_purchase_url( 'wp-career-board' );

The one extension point Pro exposes for pricing is the wcbp_consumer_cost filter, applied inside each consumer's cost callback when Pro registers with the SDK:

// Args: ( int $base_cost, int $user_id, int $item_id, int $board_id, string $consumer_slug )
add_filter( 'wcbp_consumer_cost', function ( $cost, $user_id, $item_id, $board_id, $consumer ) {
    // 'my_pro_tier_check' stands for your own membership test.
    if ( 'job_post' === $consumer && my_pro_tier_check( $user_id ) ) {
        return max( 0, (int) ( $cost / 2 ) );
    }
    return $cost;
}, 10, 5 );

See 04-credits-sdk.md for how Pro registers its consumers, adapters, and gateways with the SDK.

Hooking the board picker to filter by group membership

Free's job-form template fires apply_filters( 'wcb_board_options_for_employer', $options, $user_id ). Pro's BP-groups integration consumes it to drop boards whose linked BuddyPress group the employer is not a member of:

add_filter( 'wcb_board_options_for_employer',
    array( BpGroupBoards::class, 'restrict_boards_to_user_groups' ),
    10, 2
);

This is the canonical pattern for "Pro adds a constraint to a Free control surface."

How Pro extends Free's blocks

Free's blocks render server-side. Pro extends them via two mechanisms:

1 - Form field injection

Free's forms expose declarative field-schema filters that Pro's field builder hooks to inject custom field groups: wcb_job_form_fields, wcb_company_form_fields, wcb_candidate_form_fields, and wcb_resume_form_fields. Each passes the current field array plus a context id: the board id for jobs, the company id for companies, the candidate's user id for candidates, and the resume id for resumes:

add_filter( 'wcb_job_form_fields', function ( array $fields, int $board_id ) {
    $fields['my_group'] = array( /* field definitions */ );
    return $fields;
}, 10, 2 );

Pro persists the submitted values on the wcb_job_created / wcb_job_updated actions.

2 - REST response filtering

REST responses go through wcb_rest_prepare_* filters. Pro adds Pro-specific fields to the board, board-stage, resume, and notification responses (wcb_rest_prepare_board, wcb_rest_prepare_board_stage, wcb_rest_prepare_resume, wcb_rest_prepare_notification):

add_filter( 'wcb_rest_prepare_resume', function ( $row, $resume, $request, $context ) {
    $row['my_extra_field'] = get_post_meta( $resume->ID, '_my_extra', true );
    return $row;
}, 10, 4 );

These two patterns cover most of Pro's UI extensions. Anything they can't handle is a real gap in Free's hook surface - file a Free PR to add the hook, then consume it from Pro.

How Pro adds new database tables

Pro creates these tables: wcb_field_groups, wcb_field_definitions, wcb_field_values, wcb_job_alerts, wcb_application_stages, wcb_ai_vectors, wcb_notifications and wcb_push_devices. The credit ledger and gateway log tables belong to the bundled Credits SDK, which creates them itself. Pro creates its tables with dbDelta() in core/class-pro-install.php:

private static function create_field_groups_table( $wpdb ): void {
    $table_name = $wpdb->prefix . 'wcb_field_groups';
    $charset    = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE {$table_name} ( ... ) {$charset};";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
}

The pattern (one private method per table) makes the schema greppable. Schema version is tracked in wcbp_db_version option.

How Pro extends the credit-purchase flow

Pro registers everything (slug, consumers, and settings) with the Wbcom Credits SDK through its wbcom_credits_sdk_registry action in wp-career-board-pro.php:

add_action( 'wbcom_credits_sdk_registry', function ( \Wbcom\Credits\Registry $registry ) {
    $registry->register( array(
        'slug'      => 'wp-career-board',
        'prefix'    => 'wcb',
        'version'   => WCBP_VERSION,
        'file'      => WCBP_FILE,
        'user_type' => 'employer',
        'consumers' => array( /* job_post, featured_upgrade */ ),
        'settings'  => array( /* low_threshold, purchase_url, admin_settings_hook */ ),
    ) );
} );

The SDK ships the e-commerce adapters (WooCommerce, WC Subscriptions, WC Memberships, PMPro, MemberPress); each adapter listens for that plugin's "order completed" event and writes a topup row to the ledger. Adapters self-discover when the host plugin is active - Pro does not register them one by one. To add support for a new e-commerce plugin, write a new adapter class that implements AdapterInterface. See 04-credits-sdk.md.

Local checks

bin/architecture-checks.sh runs the architecture checks, including A1, A2 and A3. If you're authoring against Pro:

composer arch-checks   # Run the gate manually anytime
composer ci            # Run the full local pipeline

composer install-hooks turns on the repository's git hooks, including a pre-push hook that runs the local checks.

When the contract doesn't fit

If you find yourself wanting to do something the four invariants don't allow (e.g. modify Free source, register a colliding REST path), STOP and either:

  1. Open a PR against Free to add the missing extension point, or
  2. Build the feature inside Pro using a different mechanism, or
  3. Talk to the team - there's usually a third option we'd rather ship than break the contract.

The contract keeps the two plugins independent: each can be updated and tested without patching the other.

Pro hooks reference

Use these hooks to react to what Pro does and to change how it behaves. Pro fires its own wcbp_* actions and filters, plus a few hooks in the Free wcb_* namespace where Pro shares the contract with Free. It also answers a set of Free filters. For Free's hooks see the Free developer guide.

Actions Pro fires

Hook Args Use to
wcbp_application_stage_changed $app_id, $old_stage, $new_stage A person moved a card to another stage on the Kanban board, through PUT /applications/{id}/stage. Args are the application ID and the old and new stage IDs (integers). Pro's own status sync listens here.
wcbp_board_deleted $board_id A board was deleted through DELETE /boards/{id}. Pro has already removed the board's stages and unlinked its jobs when this fires.
wcbp_credit_consumed $user_id, $amount, $item_id The SDK recorded a credit deduction for this plugin (re-emitted from the SDK's wbcom_credits_deducted, scoped to this plugin). $item_id is usually the job. Use for logging or per-purchase notifications.
wcbp_credits_low $user_id, $balance The SDK reported a credit balance at or below the configured low threshold (re-emitted from the SDK's wbcom_credits_low, scoped to this plugin).
wcbp_credits_topped_up $user_id, $amount, $note The SDK recorded a credit top-up (re-emitted from the SDK's wbcom_credits_topped_up, scoped to this plugin).
wcbp_field_group_saved $group_id A field-builder group was created or updated.
wcbp_field_group_deleted $group_id A field-builder group was deleted.
wcbp_field_definition_saved $field_id, $group_id A field-builder field definition was created or updated ($group_id is 0 on update-by-id).
wcbp_field_definition_deleted $field_id A field-builder field definition was deleted.
wcbp_field_value_saved $post_id, $key, $value A custom field value on a job/company/candidate/resume was saved via the field builder.
wcbp_resume_published $resume_id, $post A candidate's resume went public. $post is the WP_Post. Use for search indexing or notifications.
wcbp_send_alert_email $alert, $jobs Pro is sending a job-alert email through its built-in email channel. $alert is the alert row, $jobs the matched job IDs. To add another channel such as SMS or Slack, use the wcbp_alert_dispatch_channels filter instead.
wcbp_open_to_work_before_item $resume, $user, $user_id Render extra markup before each Open-to-Work listing item.
wcbp_open_to_work_after_item $resume, $user, $user_id Render extra markup after each Open-to-Work listing item.
wcbp_my_applications_table_header $is_employer_view Render extra <th> cells at the end of the My Applications table header. $is_employer_view is true on the employer-facing view, false on the candidate view.
wcbp_my_applications_table_row $application, $job_id, $is_employer_view Render extra <td> cells at the end of each My Applications row. $application is the application WP_Post. Pair with wcbp_my_applications_table_header so column counts line up.
wcbp_credit_hold_reconciled $employer_id, $post_id, $amount, $orphan The daily wcbp_reconcile_credit_holds cron auto-refunded a credit hold that had no matching deduction or refund after 24 hours (crashed request, dropped REST call). $amount is the original hold amount (positive int); $orphan is the raw ledger row. Hook here to notify an admin or employer.
wcbp_ai_score_application $app_id Single-event cron action that scores one application in the background. Pro schedules it for each new application when "Auto-score applicants on submit" is on, and again after a failed scoring attempt. You can fire it yourself with an application ID. See 05-ai-providers.md.
wcbp_application_stage_assigned $app_id, $stage_id, $board_id The system placed an application in a pipeline stage (on apply, or when a status change moves the card). Not fired for a person dragging a card. Use it to greet a new applicant.
wcbp_default_stages_seeded $board_id, $first_id A board was given the default pipeline stages. $first_id is the first stage.
wcbp_guest_alert_created $alert_id, $email A visitor without an account saved a job alert. Pro's confirmation email (double opt-in) runs from this.
wcbp_post_geocoded $post_id, $lat, $lng, $location A job or resume got its coordinates from the background geocoder.

Pro also fires Free hooks in places where the action semantically belongs to Pro but the contract is shared:

Hook Where Pro fires it Why
wcb_application_status_changed modules/pipeline/class-pipeline-module.php Pro does not fire this itself. When a card lands in a stage whose outcome is Hired or Rejected, Pro asks Free's application lifecycle to set that status, and Free fires this action with ($app_id, $old_status, $new_status, $reason, $by). Moving a card out of an outcome stage sets the status back to reviewing.
wcb_resume_form_simple_extra_fields blocks/resume-form-simple/render.php Extension point for adding fields to the quick resume form. Passes $attributes.
wcb_add_more_info_hero_actions blocks/resume-single/render.php Extension point for adding buttons to the resume hero. Args: $post (the resume WP_Post), $user_id (the owner), $resume (the resume data array).
wcb_job_csv_imported modules/migration/class-csv-importer.php Fired once per imported job row with ($post_id, $data).
wcb_job_imported modules/migration/class-csv-importer.php Fired once per imported job with ($post_id).
wcb_notification_created modules/notificationsbell/class-notifications-bell-module.php Fired after a bell notification row is inserted, with one array arg { user_id, event_type, message, link, id } (id = inserted row id), so a centralised notification center (BuddyNext) can mirror it. It passes the community notification contract as a second argument (null for an admin-only row); see "Community notification contract" below. Shared wcb_ name so one listener covers Free + Pro; Free fires the same hook from its email send. Pro's PushModule also consumes this event to send native push notifications through Expo - see "Push notifications" below.
wcb_job_board_id modules/pipeline/class-stage-repository.php (StageRepository::board_for_job()) Free-owned filter (fired by Free's Jobs REST endpoint; Pro's BoardsProModule::resolve_board_id() supplies the multi-board answer). Pro's pipeline applies it to resolve a job's owning board, so a stage move can't be written to a stage from another employer's board. ($board_id, $job_id).
wcb_board_credit_cost modules/credits/class-job-charge.php Free-owned filter (Free's job forms and Jobs REST endpoint apply it when a job is posted). Pro answers it with the per-board credit_cost setting, and JobCharge applies it again to work out the price of a renewal. ($cost, $board_id).
wcb_job_republish_credit_cost modules/credits/class-job-charge.php Free-owned filter. Free applies it when a closed or expired job is republished, and Pro's JobCharge applies it to the credits it holds for the renewal, starting from the board's normal cost. One callback can discount both. ($cost, $post, $previous_status).
wcb_shortcode_attr_aliases core/class-pro-plugin.php Free-owned camelCase-attribute remap (shortcode attributes lowercase, block.json schemas don't). Pro's shortcode-to-block bridge applies it so Pro's shortcodes (for example [wcbp_featured_candidates]) share the same attribute vocabulary as Free's. ($aliases).

Filters Pro fires

AI

Hook Returns
wcbp_ai_provider_drivers array - map of provider slug to a factory callable returning an AiDriverInterface. Built-in slugs are claude, openai and ollama. Args: $drivers, $credential, $base_url (the last two hold the same value).
wcbp_ai_provider_requires_api_key bool - does the provider need a key (default true)? Args: $requires, $provider.
wcbp_candidate_resume_data array - the grouped resume data sent to AI for scoring and matching. Arg: $user_id.
wcbp_ai_candidate_matches array - the AI candidate-match results before they are returned (args: $matches, $user_id)
wcbp_ai_ranked_applications array - the AI applicant-ranking results before they are returned (args: $ranked, $job_id)
wcbp_ai_claude_model string - the Claude model id used for analysis and ranking. Defaults to the wcbp_ai_anthropic_model option.
wcbp_ai_score_batch_size int - applications scored per background pass (default 25, clamped to 1-100).
wcbp_ai_rank_max_applications int - most applications one rank request scores (default 500). Args: $max, $job_id.
wcbp_ai_match_scan_cap int - number of newest published jobs scored per candidate-match search (default 2000). Bounds the nearest-neighbor scan so a large catalog does not compare every stored vector on each request.

wcbp_ai_anthropic_model is an option (set on the AI settings screen), not a filter. It stores the chosen Claude model id and is read with get_option() as the default value the wcbp_ai_claude_model filter then applies. Override the model at runtime through that filter; change the saved default through the option.

Alerts

Hook Returns
wcbp_alert_dispatch_channels array - map of channel slug to callable( $alert, $job_ids ). The built-in email channel is present by default. Add your own channel, for example Slack or SMS.
wcbp_alerts_notify_on_import bool - whether an imported job sends instant alert emails like a fresh posting (default false). Args: $notify, $job_id. Return true to send alerts for imported jobs.

Credits SDK

Hook Returns
wcbp_consumer_cost int - actual credits charged for a consumer. Args: $base_cost, $user_id, $item_id, $board_id, $consumer_slug. Tier-pricing happens here (e.g. BpTieredCreditCost).

Kanban / pipeline

Hook Returns
wcbp_kanban_card_columns array - extra columns shown on each Kanban card
wcbp_kanban_include_unassigned bool - whether applications with no stage are folded into the first column (default true). Args: $include, $job_id, $board_id.
wcbp_pipeline_board_for_job int - the board whose stages a job's pipeline uses. Args: $board_id, $job_id. Lets a job have a dedicated pipeline without changing where it is listed.
wcbp_default_pipeline_stages array - the stage rows seeded on a new board (each has a terminal_outcome of empty, hired or rejected). Return an empty array to skip seeding. Args: $stages, $board_id.
wcbp_kanban_stage_limit int - cards fetched per stage per page on the Kanban board (default 25, clamped to 1-100).

Maps and geocoding

Hook Returns
wcbp_geocode_rate_limit int - uncached place lookups one IP address may make per hour through GET /geocode (default 30, 0 turns the limit off).
wcbp_geocode_backfill_batch int - rows geocoded per background pass (default 25, clamped to 1-100).
wcbp_geocode_throttle_us int - pause in microseconds between two backfill lookups (default 1100000, 1.1 seconds).
wcbp_non_geographic_location_terms array - lowercase location values never sent to the geocoder (default: remote, anywhere, worldwide, hybrid, other, work from home, wfh).

PWA

Hook Returns
wcbp_pwa_manifest array - the PWA manifest before it is served at /wcb-manifest.json

Resume builder

Hook Returns
wcbp_resume_groups array - the resume-form field groups (Personal, Experience, Education, Skills, etc.)
wcbp_resume_textarea_fields array - fields rendered as textareas vs single-line inputs
wcbp_resume_checkbox_fields array - fields rendered as checkboxes
wcbp_resume_date_fields array - fields formatted as date inputs
wcbp_resume_proficiency_scale array of {value, percent} - the skill/language proficiency level table for a repeater group. Args: $scale, $group_key. Drives both the input dropdown values and the resume-single progress bar.
wcbp_resume_experience_bands array of {slug, label, min, max} - the years-of-experience band table used to resolve a candidate's experience-level slug.
wcbp_resume_primary_fields array - the field keys shown on each resume section's compact card (e.g. experience => [job_title, company]), before the first-2-fields fallback. Rendered in blocks/resume-builder/render.php.
wcbp_resume_field_label string - override the label of a field. Args: $label, $field.
wcbp_resume_pdf_renderer callable or null - return a callable ( string $html, int $post_id ) that returns the PDF bytes to replace the built-in DomPDF renderer. Args: $renderer, $post_id.

Pro also extends these Free filters:

Hook What Pro returns
wcb_rest_prepare_board Adds Pro-specific board metadata to the boards response.
wcb_rest_prepare_board_stage Pipeline-stage data shape.
wcb_rest_prepare_notification Notifications bell response shape.
wcb_rest_prepare_resume Resume profile shape. Args: $data, $resume, $request, $context (single, list, create, save or pdf_replace).
wcb_job_form_fields Injects custom job field groups (field builder).
wcb_company_form_fields Injects custom company field groups.
wcb_candidate_form_fields Injects custom candidate field groups.
wcb_resume_form_fields Injects custom resume field groups.
wcb_resume_form_initial_state array - the resume builder's initial Interactivity-API state. Args: $state, $resume_id. Extend for a custom section's state keys bound by a wcb_resume_form_fields field renderer.
wcb_resume_form_simple_initial_state array - the quick resume form's initial Interactivity-API state. Args: $state, $attributes (block attributes, not a resume id - the simple form can render for a not-yet-created resume).
wcb_board_options_for_employer Restricts the board picker to the employer's BuddyPress groups.

Per-board credit cost is not a Free filter. The cost is resolved inside Pro's SDK consumer cost callback from BoardSettings::get() and then run through wcbp_consumer_cost.

Free filters Pro answers or fires

Free declares these filters. Pro answers them so Free features light up.

Hook Args What Pro does
wcb_employer_credit_has_history $has, $user_id Returns true when the employer has any row in the credit ledger. Free uses it to show the low-balance warning only to employers who have held credits.
wcb_pro_active, wcb_pro_licensed, wcb_pro_version $default Report that Pro is installed, whether the license is valid, and the Pro version.
wcb_pro_alerts_enabled, wcb_pro_resumes_enabled, wcb_pro_ai_enabled $default Report which Pro modules are present.
wcb_app_enabled $enabled True only when Pro is active and the license is valid. This gates the mobile app connection only, not the web features.
wcb_job_pipeline_url $url, $job_id Returns the Hiring Pipeline page with ?job=ID. Free uses it for the Pipeline button on employer job rows.
wcb_community_notification_types $types Adds Pro's own notification type. The shared types come from Free.
wcb_email_announces_notification $announce, $email_id, $user_id Stops Pro emails the bell already announces from announcing a second time.
wcb_resume_pdf_attachment_id $attachment_id, $resume_id, $user_id Builds and caches a PDF of a structured resume so a candidate can apply in one tap.
wcb_page_definitions, wcb_settings_schema, wcb_settings_tabs array Add the Hiring Pipeline, Job Map and Find Candidates pages, Pro settings, and Pro settings tabs.
wcb_can_browse_candidates $can, $user_id, $level Fired by Pro. Change who may browse the candidate directory. $level is the setting: public, members or approved.
wcb_can_view_resume_profile $can, $user_id, $level Fired by Pro. Change who may open a single resume.
wcb_is_approved_employer $approved, $user_id Fired by Pro. Decide who counts as an approved employer for the approved level.

Community notification contract

Every bell notification Pro records fires wcb_notification_created with two arguments: the original payload array and the community notification contract (or null when the row is admin-only). A notification center such as BuddyNext listens with accepted_args = 2. The contract fields and the builder are documented in the Free hooks reference under "Community notification contract". A listener registered with one argument, like Pro's own push module, still works.

Hooks that do not exist

  • wcb_featured_upgrade_requested, _completed and _failed are not fired anywhere in Pro. Pro charges the featured upgrade itself through its job charge code. Third-party code that wants the credits SDK to hold, deduct or refund for its own consumer defines its own hook names; see Credits SDK.

Push notifications

Native (Expo) push, in modules/push/class-push-module.php, does not add a new hook. PushModule::boot() consumes the existing wcb_notification_created action - the same event the in-app notification bell listens to - and fans each payload out to the user's registered Expo devices via the shared AsyncScheduler. There is one notification event and one source of truth; a site adding a channel doesn't need to learn a push-specific hook, only wcb_notification_created.

Device registration/unregistration is REST-only, not hook-based - see POST/DELETE /wcb/v1/push/register-device in 02-extending-free.md. PushModule exposes two static helpers other Pro code can call directly: PushModule::register_device( $user_id, $token, $platform, $device_name ) and PushModule::unregister_device( $token ).

Listening patterns

Send a Slack message when a card is moved to Hired

wcb_application_status_changed fires with ($app_id, $old_status, $new_status, $reason, $by). Free fires it, and Pro triggers it when a card lands in a stage with the Hired or Rejected outcome:

add_action( 'wcb_application_status_changed', function ( $app_id, $old_status, $new_status ) {
    if ( 'hired' !== $new_status ) {
        return;
    }
    $job_id    = (int) get_post_meta( $app_id, '_wcb_job_id', true );
    $job_title = get_the_title( $job_id );
    wp_remote_post( SLACK_WEBHOOK, array(
        'body'    => wp_json_encode( array( 'text' => "Hired: {$job_title}" ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
    ));
}, 10, 3 );

Add a custom group to the resume builder

add_filter( 'wcbp_resume_groups', function ( $groups ) {
    $groups['portfolio'] = array(
        'label'  => __( 'Portfolio links', 'my-addon' ),
        'fields' => array(
            'github'    => array( 'type' => 'url', 'label' => 'GitHub' ),
            'linkedin'  => array( 'type' => 'url', 'label' => 'LinkedIn' ),
            'dribbble'  => array( 'type' => 'url', 'label' => 'Dribbble' ),
        ),
    );
    return $groups;
});

Notify an employer when a stale credit hold auto-refunds

wcbp_credit_hold_reconciled fires once per orphaned hold the daily reconciler cron refunds (a hold left open more than 24h with no matching deduction or refund - typically a crashed request):

add_action( 'wcbp_credit_hold_reconciled', function ( $employer_id, $post_id, $amount, $orphan ) {
    wp_mail(
        get_userdata( $employer_id )->user_email,
        __( 'Credits refunded for an interrupted job post', 'my-addon' ),
        sprintf( '%d credits were auto-refunded for job #%d.', $amount, $post_id )
    );
}, 10, 4 );

Tier the credit cost by user role

add_filter( 'wcbp_consumer_cost', function ( $cost, $user_id, $item_id, $board_id, $consumer ) {
    // 'my_pro_tier_check' stands for your own membership test.
    if ( 'job_post' === $consumer && my_pro_tier_check( $user_id ) ) {
        return max( 0, (int) ( $cost / 2 ) );  // 50% off for premium employers
    }
    return $cost;
}, 20, 5 );

How to confirm an arg signature

grep -rn "do_action\\s*(\\s*'wcbp_credit_consumed'" wp-content/plugins/wp-career-board-pro/

The result shows the file where Pro fires the hook. Read the lines around it for the parameter shapes.

Wbcom Credits SDK

Use this page to register a credit-spending feature, add a credit source, or read and write the credit ledger. The credit system is built on the Wbcom Credits SDK - a bundled library at libs/wbcom-credits-sdk/ (kept in libs/, not vendor/, so it always ships in the release zip). It provides:

  • An append-only ledger (the {prefix}_credit_ledger table; for this plugin the prefix is wcb, so wp_wcb_credit_ledger).
  • A consumer pattern (entities that spend credits - job posting, featured upgrade).
  • An adapter pattern for e-commerce plugins (WooCommerce, WC Subscriptions, WC Memberships, PMPro, MemberPress).
  • A gateway pattern for direct payment processors (Stripe, PayPal).

This doc covers the contract for registering a slug and writing your own consumer, adapter, or gateway.

Architecture

            +-------------------------------------------+
            |  Wbcom Credits SDK (libs/)                |
            |                                           |
            |  +--------------+                         |
            |  | Ledger       |  <- single source       |
            |  | (DB writes)  |     of truth            |
            |  +--------------+                         |
            |        ^                                  |
            |   +----+----+----------+                  |
            |   |         |          |                  |
            | Consumers  Adapters  Gateways             |
            | (job_post, (Woo,     (Stripe,             |
            |  featured)  WCS, WCM, PayPal -            |
            |             PMPro,   direct)              |
            |             MemberPress)                  |
            +-----^----------^----------^---------------+
                  |          |          |
              hold/deduct  on order  on webhook
              on actions   completed verified

Registering your slug with the SDK

A plugin registers everything (slug, prefix, consumers, settings) in one call on the wbcom_credits_sdk_registry action, which fires before the SDK loads. Pro does this in wp-career-board-pro.php:

add_action( 'wbcom_credits_sdk_registry', function ( \Wbcom\Credits\Registry $registry ) {
    $registry->register( array(
        'slug'      => 'wp-career-board',
        'prefix'    => 'wcb',              // table prefix: {wp}_wcb_credit_ledger
        'version'   => WCBP_VERSION,
        'file'      => WCBP_FILE,
        'user_type' => 'employer',
        'consumers' => array( /* see below */ ),
        'settings'  => array(
            'low_threshold'       => 5,
            'purchase_url'        => '',
            'admin_settings_hook' => 'wcb_admin_settings_tabs',
        ),
    ) );
} );

Consumers - what can spend credits

A "consumer" is something the SDK debits credits FOR. Each consumer declares three lifecycle actions: hold_on (reserve credits), deduct_on (settle the hold permanently), and refund_on (release the hold). The SDK adds the listeners; you fire the actions. The cost callback receives the item id and returns the credit cost.

Pro registers two consumers inside the consumers array of its register() call. Neither uses the hold_on / deduct_on / refund_on actions. Pro's JobCharge class drives them from the job's lifecycle instead, so every path is covered (auto-publish, approving a draft, resubmitting, changing board, bulk and command-line approval):

'consumers' => array(
    array(
        'id'    => 'job_post',
        'label' => __( 'Job Posting', 'wp-career-board-pro' ),
        // Priced for the job's author, never the current user.
        'cost'  => static function ( int $item_id ): int {
            $user_id  = (int) get_post_field( 'post_author', $item_id );
            $board_id = (int) get_post_meta( $item_id, '_wcb_board_id', true );
            $base     = $board_id > 0
                ? (int) ( ( new \WCB\Pro\Modules\Boards\BoardSettings() )->get( $board_id )['credit_cost'] ?? 0 )
                : 0;
            return (int) apply_filters( 'wcbp_consumer_cost', $base, $user_id, $item_id, $board_id, 'job_post' );
        },
    ),
    array(
        'id'    => 'featured_upgrade',
        'label' => __( 'Featured Upgrade', 'wp-career-board-pro' ),
        'cost'  => static function ( int $item_id ): int {
            $user_id = (int) get_post_field( 'post_author', $item_id );
            $base    = (int) get_option( 'wcbp_featured_upgrade_cost', 10 );
            return (int) apply_filters( 'wcbp_consumer_cost', $base, $user_id, $item_id, 0, 'featured_upgrade' );
        },
    ),
),

JobCharge places a hold when an employer submits a job (a 402 if the balance is short), settles it when the job goes live, and releases it when the job is rejected, trashed or deleted before it went live. Pro does not fire wcb_featured_upgrade_requested, _completed or _failed.

To add your own consumer, append another entry to the consumers array in your own register() call (or call $registry->register() again for a separate slug). The cost callback signature is function ( int $item_id ): int. Either give the entry hold_on, deduct_on and refund_on action names and fire those actions when the lifecycle events happen in your code, or drive the consumer yourself as JobCharge does. The SDK takes care of the ledger writes.

Adapters - automatic credit grants from e-commerce plugins

An "adapter" listens for a specific plugin's purchase event and writes a topup ledger row. The SDK ships five adapters, which register themselves when their host plugin is active:

Adapter File Listens to
WooCommerce libs/wbcom-credits-sdk/src/Adapters/WooCommerce.php woocommerce_order_status_completed and woocommerce_order_status_processing
WC Subscriptions libs/wbcom-credits-sdk/src/Adapters/WooSubscriptions.php woocommerce_subscription_payment_complete and woocommerce_subscription_renewal_payment_complete
WC Memberships libs/wbcom-credits-sdk/src/Adapters/WooMemberships.php wc_memberships_user_membership_status_changed
Paid Memberships Pro libs/wbcom-credits-sdk/src/Adapters/PMPro.php pmpro_after_change_membership_level and pmpro_subscription_payment_completed
MemberPress libs/wbcom-credits-sdk/src/Adapters/MemberPress.php mepr_event_transaction_completed

Each adapter implements AdapterInterface (libs/wbcom-credits-sdk/src/Adapters/AdapterInterface.php). Note the methods are instance methods, not static:

interface AdapterInterface {
    public function get_id(): string;
    public function get_label(): string;
    public function is_available(): bool;             // host plugin active?
    public function register_hooks( string $slug ): void;
    public function get_mappable_items(): array;       // products/levels for the admin mapping UI
}

To add a new adapter (e.g. for Easy Digital Downloads), implement the interface, hook the host plugin's purchase event in register_hooks(), and write a topup row with Credits::topup(). Register the adapter from the SDK's wbcom_credits_register_adapters action, which passes the adapter registry and the slug:

namespace MyAddon\Credits;

use Wbcom\Credits\Adapters\AdapterInterface;
use Wbcom\Credits\Credits;

class EDD implements AdapterInterface {

    public function get_id(): string {
        return 'edd';
    }

    public function get_label(): string {
        return 'Easy Digital Downloads';
    }

    public function is_available(): bool {
        return class_exists( 'Easy_Digital_Downloads' );
    }

    public function register_hooks( string $slug ): void {
        add_action( 'edd_complete_purchase', function ( $payment_id ) use ( $slug ) {
            $user_id = (int) edd_get_payment_user_id( $payment_id );
            foreach ( edd_get_payment_meta_cart_details( $payment_id ) as $item ) {
                $credits = (int) $this->credits_for_product( $slug, (int) $item['id'] );
                if ( $credits > 0 ) {
                    // Signature: topup( $slug, $user_id, $amount, $note )
                    Credits::topup( $slug, $user_id, $credits, 'EDD order #' . $payment_id );
                }
            }
        });
    }

    public function get_mappable_items(): array {
        // Return EDD products in the shape the admin mapping UI expects.
        return array();
    }

    private function credits_for_product( string $slug, int $product_id ): int {
        $mappings = (array) get_option( "{$slug}_credit_mappings", array() );
        foreach ( $mappings as $row ) {
            if ( 'edd' === ( $row['adapter'] ?? '' ) && (int) $row['item_id'] === $product_id ) {
                return (int) $row['credits'];
            }
        }
        return 0;
    }
}

SDK REST routes

The SDK registers its own REST surface per registered slug, under the SDK's own wbcom-credits/v1 namespace - separate from the plugin's wcb/v1 namespace (Pro's GET /wcb/v1/employers/{id}/credits, documented in 02-extending-free.md, is a thin Pro-side read of the same ledger, not part of this surface).

Registry::register() wires the REST class, which registers three routes:

GET   /wbcom-credits/v1/wp-career-board/balance   Current user's balance (or ?user_id= for an admin).
GET   /wbcom-credits/v1/wp-career-board/history   Paginated ledger entries (user_id, limit, offset; default limit 50).
POST  /wbcom-credits/v1/wp-career-board/topup     Admin manual credit change: { user_id, amount, note }. The amount is signed.

balance and history need a logged-in user reading their own data, or an administrator (manage_options) reading anyone's through user_id. topup needs manage_options.

Gateways - direct payment processors

A "gateway" is for selling credits directly without an e-commerce plugin in between (Stripe Checkout, PayPal). The SDK ships two gateways: Stripe and PayPal (libs/wbcom-credits-sdk/src/Gateways/).

The SDK's Webhook_Controller registers four more REST routes per slug, in the same wbcom-credits/v1 namespace:

POST  /wbcom-credits/v1/wp-career-board/checkout/{gateway}   Logged in. Create a hosted checkout session.
POST  /wbcom-credits/v1/wp-career-board/webhook/{gateway}    Public, provider-signed. Adjusts the ledger.
POST  /wbcom-credits/v1/wp-career-board/claim/{gateway}      Logged in. Credit a paid checkout when the buyer returns, body { session_id }.
POST  /wbcom-credits/v1/wp-career-board/refund/{gateway}     Administrator. Refund a prior checkout.

The webhook checks the gateway's verify_signature() before it handles an event, so the request itself is authenticated by the provider signature. The claim route lets a site without a working webhook credit a paid checkout on return; the payment details come from the provider, not from the browser.

The browser side of checkout/{gateway} doesn't need a hand-rolled fetch(): the SDK ships a reusable helper, assets/js/checkout.js, registered as the wbcom-credits-checkout script handle (once, however many plugins register) and localized with wbcomCreditsCfg = { restRoot, nonce }. Enqueue it where you render a buy button and call the global it exposes:

wp_enqueue_script( 'wbcom-credits-checkout' ); // Where the buy button renders.
// JS: on click
window.wbcomCreditsCheckout( {
    slug:      'wp-career-board',
    gateway:   'stripe',
    pack_id:   'pack_50',
    credits:   50,
    returnUrl: window.location.href,
} );
// POSTs to /{slug}/checkout/{gateway} with the REST nonce, then redirects
// the browser to the hosted checkout URL the SDK returns.
// Optional: billing (object) and coupon (string). Send pack_id or credits.

The same script exposes window.wbcomCreditsClaim( slug ), which calls the claim route when the page is a checkout return.

If you're writing a custom gateway, implement GatewayInterface (libs/wbcom-credits-sdk/src/Gateways/GatewayInterface.php). Extend Abstract_Gateway, which supplies the webhook handling: you implement normalize_event() and the other interface methods, and do not override handle_webhook(). Register your gateway from the wbcom_credits_register_gateways action, which passes the gateway registry and the slug:

interface GatewayInterface {
    public function get_id(): string;
    public function get_label(): string;
    public function is_available(): bool;
    public function get_settings_fields(): array;
    public function create_checkout( string $slug, int $user_id, int $credits,
                                     int $price_cents, string $currency = 'USD',
                                     ?string $return_url = null ): string;
    public function verify_signature( string $raw_body, array $headers ): bool;
    public function normalize_event( array $payload ): ?Gateway_Event;
    public function handle_webhook( string $slug, array $payload ): \WP_REST_Response;
    public function refund( string $slug, string $session_id, ?int $amount_cents = null ): bool;
}

The ledger

Every credit movement writes one row. The table is named {wp_prefix}{prefix}_credit_ledger (for this plugin, wp_wcb_credit_ledger); the SDK creates one ledger table per registered prefix, so the table itself scopes the data and there is no slug column. Schema:

Column Type Notes
id bigint unsigned PK Auto-increment
user_id bigint unsigned The credit holder (employer)
item_id bigint unsigned The consumed entity (job, etc.); 0 for top-ups/adjustments
entry_type varchar(20) One of topup, hold, deduction, refund
amount int Signed: positive for topup/refund, negative for hold/deduction
note varchar(255) Free-form context string
expires_at datetime, null When the credits lapse; empty for never
reason varchar(32) What happened, such as topup, purchase, spend or hold_release
reference varchar(191) The order or session the row came from
hold_id bigint unsigned The hold this row settles or releases; 0 otherwise
created_at datetime Defaults to CURRENT_TIMESTAMP

The balance is the sum of amount for the user. Rows are only added, except that cancel_hold() deletes an open hold.

To read the ledger:

$balance = \Wbcom\Credits\Credits::get_balance( 'wp-career-board', $user_id );
$rows    = \Wbcom\Credits\Credits::get_ledger( 'wp-career-board', $user_id, 50 );
// or directly: \Wbcom\Credits\Ledger::get_history( 'wcb', $user_id, $limit, $offset )

Never INSERT/UPDATE the ledger directly - use the Credits helpers, which use these exact signatures:

Credits::topup(  string $slug, int $user_id, int $amount, string $note = '', ?string $expires_at = null, string $reason = 'topup', string $reference = '', int $item_id = 0 ): int|false;
Credits::hold(   string $slug, int $user_id, int $amount, int $item_id, string $note = '' ): int|false;
Credits::deduct( string $slug, int $user_id, int $amount, int $item_id, string $note = '' ): bool;
Credits::refund( string $slug, int $user_id, int $amount, int $item_id, string $note = '' ): int|false;
Credits::cancel_hold( string $slug, int $user_id, int $item_id ): void;
Credits::adjust( string $slug, int $user_id, int $amount, string $note = '' ): int|false;
Credits::get_cost( string $slug, string $consumer_id, int $item_id = 0 ): int;
Credits::get_purchase_url( string $slug ): string;

The 4th argument to topup() is a string note, not an array. Credits::deduct() settles an open hold: it writes a refund row that releases the held amount and a deduction row for the cost, in one transaction. It returns false when there is no open hold.

Where to read further

  • libs/wbcom-credits-sdk/src/ - the SDK source (bundled, not loaded over the network).
  • Pro hooks for credits in 03-hooks-reference.md: wcbp_consumer_cost (cost filter), wcbp_credit_consumed, wcbp_credits_low, and wcbp_credits_topped_up (re-emitted from the SDK's wbcom_credits_deducted, wbcom_credits_low and wbcom_credits_topped_up).

AI Providers and Endpoints

Use this page to call the AI routes, tune background scoring, or add your own AI provider.

The AI hiring tools (applicant ranking, fit scores, applicant TL;DR summaries, candidate-to-job matching, AI job-description and cover-letter writing) live in modules/ai/. They are driver-based: one driver per provider, all behind a common interface, with a filter to register a fourth provider from an addon.

Built-in providers: Anthropic Claude, OpenAI, and self-hosted Ollama. Providers are chosen per task - an analysis and ranking provider (Claude, OpenAI, or Ollama) and an embedding/matching provider (OpenAI or Ollama) - each with its own key, under Settings > AI Settings.

REST endpoints

All AI routes live under the shared wcb/v1 namespace and are registered by api/endpoints/class-ai-endpoint.php. Every route checks who may call it (the license never gates them - see the licensing note below) and counts against a per-user rate limit of 30 AI requests per hour; the 31st returns wcb_rate_limit with HTTP 429.

Method Route Permission Purpose
POST /wcb/v1/ai/match logged in Jobs that match a natural-language query (AI Chat Search) or the current user's resume. Needs an embedding provider.
GET /wcb/v1/candidates/{id}/matches that user, or wcb/manage-ai "Recommended for you" jobs for a candidate. Needs an embedding provider.
GET /wcb/v1/ai/ranked-applications/{job_id} wcb/view-applications, and the job's author (or wcb/manage-settings / wcb/moderate-jobs) Applicants for a job, best fit first. Unscored applicants have score: null and are queued for background scoring.
POST /wcb/v1/jobs/ai-description wcb/post-jobs Generate a job description.
POST /wcb/v1/jobs/{job_id}/ai-cover-letter wcb/apply-jobs Generate a cover letter from the candidate's resume and a published job. 404 for any other status, 503 when no analysis provider is set.

Fit scores, reasons, and summaries are cached per application (in the _wcbp_ai_fit_score, _wcbp_ai_fit_reason, and _wcbp_ai_summary meta family, plus _wcbp_ai_scored_at), so re-opening the Employer Dashboard never re-bills the model; ranking computes only what is missing.

Scoring and "not scored"

AiModule::score_application( $app_id, $force = false ) returns { application_id, score, reason, summary }. When the provider errors or its reply has no numeric score, it returns score: null with not_scored: true, saves nothing, and schedules another try 5, 10 and 20 minutes later (tracked in _wcbp_ai_score_tries, three tries). A failed call is never stored as a 0% fit. The dashboard shows "Not scored".

The model reads the job title and description (4,000 characters) and the application: cover letter, answers to the application form fields, and the chosen resume, else the profile resume (6,000 characters together).

Filter Default Use to
wcbp_ai_score_batch_size 25 (1-100) Applications scored per background pass
wcbp_ai_rank_max_applications 500 Applications one ranking pass considers per job
wcbp_ai_match_scan_cap 2000 Job vectors scanned per matching search

Auto-scoring on submit

When "Auto-score applicants on submit" is enabled (Settings > AI Settings, option wcbp_ai_auto_rank), Pro schedules a single cron event to score each new application in the background, unless one is already queued for it:

wp_schedule_single_event( time() + 30, 'wcbp_ai_score_application', array( $app_id ) );

The handler AiModule::run_scheduled_scoring() listens on the wcbp_ai_score_application action. To trigger scoring yourself, fire that action with an application id. An explicit rank request queues one wcbp_ai_score_job_batch event per job instead, which scores a batch of unscored applications and re-arms itself until the job is drained.

The driver interface

Every provider implements AiDriverInterface (modules/ai/class-ai-driver-interface.php):

interface AiDriverInterface {
    public function embed( string $text ): array|\WP_Error;     // vector for matching
    public function complete( string $prompt ): string|\WP_Error; // text generation
    public function provider_name(): string;
}

The built-in drivers are ClaudeDriver, OpenAiDriver, and OllamaDriver, all in modules/ai/.

Adding another provider

The driver registry is a provider_slug => factory_callable map run through the wcbp_ai_provider_drivers filter. Add a slug to ship your own provider:

add_filter( 'wcbp_ai_provider_drivers', function ( array $drivers, string $credential, string $base_url ) {
    $drivers['my_llm'] = static function () use ( $credential ): \WCB\Pro\Modules\Ai\AiDriverInterface {
        return new \MyAddon\Ai\MyLlmDriver( $credential );
    };
    return $drivers;
}, 10, 3 );

Then make your provider selectable by registering it in the AI settings UI, or set the relevant option (wcbp_ai_completion_provider / wcbp_ai_embedding_provider) to your slug.

If your provider does not need an API key (for example a self-hosted endpoint), tell Pro via the wcbp_ai_provider_requires_api_key filter:

add_filter( 'wcbp_ai_provider_requires_api_key', function ( bool $requires, string $provider ) {
    return 'my_llm' === $provider ? false : $requires;
}, 10, 2 );

Model selection

Each provider's model is configurable so you can trade quality for cost. For Claude, the model is resolved through the wcbp_ai_claude_model filter (default reads the wcbp_ai_anthropic_model option, or the driver's built-in default when unset). To force a model:

add_filter( 'wcbp_ai_claude_model', fn() => 'your-claude-model-id' );

Output and input filters

Filter Args Use to
wcbp_candidate_resume_data $user_id Override the grouped resume data Pro feeds the model when scoring or matching a candidate.
wcbp_ai_candidate_matches $matches, $user_id Post-process the candidate match results before they are returned.
wcbp_ai_ranked_applications $ranked, $job_id Post-process the applicant ranking before it is returned.

Licensing

Like every Pro feature, the AI tools are not gated on the license. The license drives automatic updates only; once Pro is installed and a provider key is set, the AI endpoints work regardless of license status. See 02-extending-free.md for the contract.

Pro REST API reference

WP Career Board Pro adds routes to the wcb/v1 namespace, on top of the routes in the Free plugin (see the Free REST API reference). This page lists the Pro routes only. Base URL: https://your-site.com/wp-json/wcb/v1.

Authentication and errors

  • Logged-in browser calls send the X-WP-Nonce header (wp_create_nonce( 'wp_rest' )). External clients use Application Passwords over HTTPS.
  • Pro routes are not gated by the license. The license only controls automatic updates, so a route works on an unlicensed site.
  • Permission failures return 401 (not logged in) or 403 (logged in, not allowed) with a WP_Error body.
  • Abilities named below (for example wcb/manage-boards) are the Free plugin's abilities. Administrators have all of them.

Application pipeline

Route Method Who may call Params Notes
/jobs/{id}/kanban GET Needs wcb/view-applications, and be an admin, a moderator (wcb/moderate-jobs), or the job's author stage_id (int, 0 = all columns), page (int, default 1) Returns one array item per stage with applications, total, has_more, page. With stage_id it returns that one column's page. 25 cards per page by default (filter wcbp_kanban_stage_limit, capped at 100).
/applications/{id}/stage PUT, PATCH, POST Needs wcb/view-applications, and be a moderator or the author of the application's job stage_id (int, required) 400 wcb_invalid_stage if the stage is not on the job's board. 409 wcb_application_closed if the application is withdrawn, position closed or job removed. Fires wcbp_application_stage_changed.

Boards and stages

Route Method Who may call Params Notes
/boards/{id} GET Anyone none Returns id, title, currency. 404 wcb_board_not_found.
/boards/{id} DELETE wcb/manage-boards none Deletes the board, its stages, and unlinks its jobs.
/boards/{id}/stages GET Logged in, and wcb/manage-boards or the board's author none Ordered stage list.
/boards/{id}/stages POST wcb/manage-boards label, color (hex, default #6366f1), sort_order, is_terminal, terminal_outcome Creates a stage.
/boards/{id}/stages/{stage_id} PUT, PATCH, POST wcb/manage-boards label, color, sort_order Send only the fields to change.
/boards/{id}/stages/{stage_id} DELETE wcb/manage-boards none Its cards move to the board's first remaining stage; the response reports moved_to_stage and applications_moved.

Field Builder

All Field Builder routes need wcb/manage-boards.

Route Method Params Notes
/fields/groups GET board_id, entity_type (default job) Lists groups.
/fields/groups POST board_id (required, 0 = global), label (required), entity_type (default job), sort_order, excluded_boards (int array) excluded_boards hides a job group on those boards.
/fields/groups/{id} PUT, PATCH, POST same as create, none required
/fields/groups/{id} DELETE none
/fields/groups/{group_id}/fields GET none Fields in a group.
/fields/groups/{group_id}/fields POST field_type (required), label (required), field_key, options (array), rules (object), visibility (public, employer_only, admin_only; default public), required (bool), sort_order Keys are stored with a wcbf_ prefix. 400 wcb_invalid_field_type, 404 wcb_group_not_found, 409 when the key already exists.
/fields/{id} PUT, PATCH, POST same as create, none required
/fields/{id} DELETE none
/fields/reorder POST items (array of objects, required) Saves drag-and-drop order.

The 17 accepted field_type values: text, textarea, number, url, email, date, date_range, select, multi_select, checkbox, radio, file, video_url, location, salary_range, repeater, conditional.

Resumes

Route Method Who may call Params Notes
/resumes GET Anyone the candidate directory access level allows (setting resume_directory_access: public, members or approved; filter wcb_can_browse_candidates). Others get 401 (logged out) or 403 page, per_page (1-50, default 12), search, skill, open_to_work, experience, location, order (ASC, DESC), author Public candidate directory. Filtering runs on the server.
/resumes POST Logged in none Creates a resume for the current user.
/candidates/{id}/resumes GET The candidate, or a user with wcb/view-resumes none Blocked candidates return 404.
/candidates/{id}/resumes POST The candidate only title (required)
/resumes/{id} GET Owner, anyone who may read that resume, or wcb/manage-settings none
/resumes/{id} PUT, PATCH, POST Owner or wcb/manage-settings title, is_public, custom_fields, sections
/resumes/{id} DELETE Owner or wcb/manage-settings none
/resumes/photo-upload POST Needs wcb/manage-resume multipart file field photo
/resumes/{id}/pdf GET Same as GET /resumes/{id} none Streams the generated PDF as a download.
/resumes/{id}/pdf POST Owner or wcb/manage-settings multipart file field resume_file (PDF only) Replaces the attached CV. 400 wcb_invalid_file_type for non-PDF.
/resumes/{id}/bookmark POST Logged in none Toggles the bookmark for the current user.

Job alerts

Route Method Who may call Params Notes
/alerts GET Logged in none The current user's alerts, up to 1000.
/alerts POST Logged in, or a guest with a valid email when guest alerts are on board_id (0 = all), search_query, filters (object: category, type), frequency (instant, daily, weekly; default daily), email (guests) Returns id and needsConfirm (true for guests, who must confirm by email). Guests: 5 requests per IP per hour (429 wcb_alert_rate_limited). Everyone: capped per person by the alerts limit (400 wcb_alert_limit).
/alerts/{id} PUT, PATCH, POST Alert owner or wcb/manage-settings frequency, search_query, filters, board_id Returns updated.
/alerts/{id} DELETE Alert owner or wcb/manage-settings none Returns deleted.
/alerts/{id}/unsubscribe/{token} GET, POST Anyone with the 32-character token none One-click unsubscribe used by the email header. 403 wcb_invalid_token if the token is wrong.

Notifications bell

All routes need a logged-in user and only touch that user's rows.

Route Method Params Notes
/notifications GET page (default 1), per_page (1-50, default 20) Returns notifications and unread_count.
/notifications DELETE none Clears all.
/notifications/{id} DELETE none
/notifications/{id}/read PUT, PATCH, POST none
/notifications/read-all POST none

Push (companion apps)

Route Method Who may call Params Notes
/push/register-device POST Logged in expo_push_token (required), platform (ios, android), device_name 400 wcb_invalid_push_token unless the token looks like ExponentPushToken[...]. Returns 201.
/push/register-device DELETE Logged in expo_push_token (required)

Credits

Route Method Who may call Notes
/employers/{id}/credits GET That employer, or wcb/manage-credits Returns balance and the 50 newest ledger rows.
/jobs/{id}/feature POST The job's author, or wcb/manage-credits Charges the Featured price and features the job. Only publish or pending jobs (409 wcb_not_featurable). Returns id, featured, balance.
/analytics/credits.csv GET wcb/view-analytics or wcb/manage-credits Streams the credit ledger as CSV, newest first.

The credit checkout, claim and webhook routes belong to the bundled Credits SDK and live under wbcom-credits/v1. See Credits SDK.

AI

Each call counts against a limit of 30 AI requests per user per hour (429 wcb_rate_limit). See AI providers.

Route Method Who may call Params
/ai/match POST Logged in query (optional; empty uses the candidate's resume)
/candidates/{id}/matches GET That candidate, or wcb/manage-ai none
/ai/ranked-applications/{job_id} GET wcb/view-applications, and an admin, moderator or the job's author none
/jobs/ai-description POST wcb/post-jobs title, company_type, location
/jobs/{job_id}/ai-cover-letter POST wcb/apply-jobs none

Geocoding

Route Method Who may call Params Notes
/geocode GET Anyone address (required, 2-200 characters) Returns { lat, lng } from the active map driver. Results are cached (one day for a hit, one hour for a miss). 30 requests per IP per hour by default (filter wcbp_geocode_rate_limit, 429 wcb_rate_limited). 422 wcbp_geocode_failed when no place is found.

Setup wizard

These three routes run the Pro steps of the setup wizard and need wcb/manage-settings.

Route Method Params
/wizard/activate-license POST license_key (required)
/wizard/setup-credits POST threshold (int, default 5)
/wizard/create-pro-pages POST none

Pro shortcodes

Every Pro block also works as a shortcode, so you can place it in a classic editor, Elementor, Beaver Builder, Bricks or Divi. Each Pro block has a shortcode of the same name pattern (wcbp_ plus the block name). Free's shortcodes are covered in the Free developer guide.

Pro shortcodes need the Free plugin active. They do not check the Pro license: the license controls updates only.

How attributes work

  • WordPress lowercases attribute names, and Pro maps them back to the block's camelCase name (jobid becomes jobId, perpage becomes perPage).
  • Whole numbers become integers, true and false become booleans, everything else stays text.
  • An attribute a block does not declare is ignored.
  • [wcbp_application_kanban jobId="123"] renders exactly what the block renders with {"jobId":123}.

Sites can add more aliases with the Free filter wcb_shortcode_attr_aliases.

Shortcode list

Shortcode Block Attributes (default)
[wcbp_resume_form] wcb/resume-form compact (false)
[wcbp_resume_form_simple] wcb/resume-form-simple showPhotoField (true), compact (false)
[wcbp_resume_builder] wcb/resume-builder none. Works on the current candidate.
[wcbp_resume_archive] wcb/resume-archive perPage (12), authorId (0), includePrivate (false)
[wcbp_resume_search_hero] wcb/resume-search-hero layout (horizontal), placeholder, buttonLabel, showSkillFilter (true), showOpenToWorkFilter (false)
[wcbp_resume_single] wcb/resume-single resumeId (0, uses the current page's resume)
[wcbp_resume_map] wcb/resume-map height (480)
[wcbp_job_map] wcb/job-map height (480)
[wcbp_credit_balance] wcb/credit-balance showHistory (true), historyCount (20, history rows per page)
[wcbp_job_alerts] wcb/job-alerts none
[wcbp_application_kanban] wcb/application-kanban jobId (0, falls back to the ?job= URL parameter)
[wcbp_my_applications] wcb/my-applications authorId (0), employerId (0), perPage (20)
[wcbp_open_to_work] wcb/open-to-work count (5), title, showViewAll (true), viewAllUrl
[wcbp_featured_candidates] wcb/featured-candidates count (5), title, showViewAll (true), viewAllUrl
[wcbp_featured_companies] wcb/featured-companies count (5), title, showViewAll (true), viewAllUrl
[wcbp_ai_chat_search] wcb/ai-chat-search placeholder

Examples

[wcbp_resume_archive perPage="12"]
[wcbp_resume_form_simple showPhotoField="false" compact="true"]
[wcbp_application_kanban jobId="123"]
[wcbp_featured_candidates count="6" title="New talent"]

Notes

  • Hiring Pipeline page. Pro creates this page with the wcb/application-kanban block and no jobId. Employers open it from a job row and the job comes from ?job=ID. Only someone who may see that job's pipeline gets the board. Anyone else sees "You don't have access to this job's pipeline."
  • Quick form or full builder. [wcbp_resume_form_simple] is a one-screen profile for sign-up flows. [wcbp_resume_builder] is the multi-section form for the "Edit my resume" page. See Resume builder overview.
  • Extra fields. The quick form has the hooks wcb_resume_form_fields, wcb_resume_form_simple_initial_state and wcb_resume_form_simple_extra_fields. See Hooks reference.
  • Blocks. Each block, with its editor settings, is listed in Pro blocks reference.

Something unclear? Open a support ticket → · Refund policy

Buy WP Career Board Pro