Skip to content

AI Providers and Endpoints

WP Career Board overviewFree + ProGet WP Career Board →

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.

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 (counted only after the permission check passes); the 31st returns wcb_rate_limited 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.

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

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.

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

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

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

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.