Skip to content

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.

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).
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.

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.
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).
Hook Returns
wcbp_kanban_card_columns array - the column array that GET /jobs/{id}/kanban returns, before it is sent. Args: $columns, $job_id. Add columns such as archived or on-hold, or annotate existing ones.
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).
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).
Hook Returns
wcbp_pwa_manifest array - the PWA manifest before it is served at /wcb-manifest.json
wcbp_pwa_host_app_active bool - whether another plugin’s app should carry the job board, so Career Board registers no manifest or worker. Default is whether BuddyNext’s app is on. Arg: $active. See PWA.
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_schema array - the resume schema (group key to label and field descriptors) that Pro builds for API clients. Arg: $schema.
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 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_job_payment $paid, $job_id, $event Free-owned filter that collects the price when an employer acts on a job. $event is create, resubmit, republish, board_change or feature. Pro’s JobCharge answers it by holding or charging credits and returns true or a WP_Error (a 402 when the balance is short). Pro takes the hold inside this filter, so a callback that runs this filter or publishes or rejects a job changes the employer’s balance: a job is held on submit, spent when it goes live, and refunded when it is rejected, trashed or deleted before then.
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.

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.

  • 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.

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 ).

Send a Slack message when a card is moved to Hired

Section titled “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_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

Section titled “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 );
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 );
Terminal window
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.