Overview
The Loxo plugin exposes a REST API for programmatic control of job synchronization, webhooks, job data, and the Google Indexing integration. All endpoints live under the loxo/v1 namespace on your own site:
https://example.com/wp-json/loxo/v1/
Replace example.com with your site’s domain in every example below. Every endpoint requires an administrator account (the manage_options capability) except Job View Tracking, which is public, and the Webhook Event Listener, which is called by Loxo itself.
Authentication
- Cookie authentication — used automatically by the plugin’s own admin screens while you are logged in to WordPress.
- Application passwords — for external integrations (WordPress 5.6+). Create one under Users → Profile → Application Passwords, then send it with HTTP Basic auth.
curl -u "admin:abcd efgh ijkl mnop" \
https://example.com/wp-json/loxo/v1/job-sync
All examples below assume the -u flag shown here.
Response Conventions
The API answers in two shapes, and knowing which to expect saves confusion:
Status envelope — the job synchronization endpoints reply with WordPress’s code / message / data.status envelope even on success. Read the HTTP status code and the code field, not the presence of an error shape:
{
"code": "sync_scheduled",
"message": "Background synchronization scheduled.",
"data": { "status": 202 }
}
Plain object — everything else replies with a flat JSON object, most often carrying a message key, plus endpoint-specific data:
{ "message": "API Cache cleared." }
Job Synchronization
One resource, five methods. The sync runs in the background; these endpoints start it and control it while it runs.
POST /wp-json/loxo/v1/job-sync
Start a background job synchronization. No parameters.
curl -X POST -u "admin:abcd efgh ijkl mnop" \
https://example.com/wp-json/loxo/v1/job-sync
Response — 202 Accepted
{
"code": "sync_scheduled",
"message": "Background synchronization scheduled.",
"data": { "status": 202 }
}
Errors: 409 already_running — another sync is already in progress.
GET /wp-json/loxo/v1/job-sync
Get the current synchronization status. message carries progress text while a sync is running.
Response — 200 OK
{
"running": true,
"paused": false,
"cancelled": false,
"process_running": true,
"message": "Synchronizing jobs..."
}
PATCH /wp-json/loxo/v1/job-sync
Pause the running synchronization. The pause takes effect at the next safe point, so poll GET until paused is true.
Response — 200 OK
{
"code": "sync_paused",
"message": "Pause requested, wait for response.",
"data": { "status": 200 }
}
Errors: 409 not_running — no sync in progress · 409 already_paused
PUT /wp-json/loxo/v1/job-sync
Resume a paused synchronization.
Response — 202 Accepted
{
"code": "sync_resumed",
"message": "Background synchronization resumed.",
"data": { "status": 202 }
}
Errors: 409 not_paused — nothing to resume · 409 already_running
DELETE /wp-json/loxo/v1/job-sync
Cancel the ongoing synchronization. Like pause, cancellation is picked up at the next safe point.
Response — 200 OK
{
"code": "sync_cancelled",
"message": "Cancellation requested, wait for response.",
"data": { "status": 200 }
}
Webhook Management
Loxo can push job changes to your site in real time through three webhooks: job.create, job.update, and job.destroy. These endpoints register and manage them on the Loxo side. All three accept one optional parameter:
| Parameter | Type | Required | Description |
|---|---|---|---|
callback_url | string | No | The URL Loxo should deliver events to. Defaults to this site’s own event listener endpoint. |
POST /wp-json/loxo/v1/loxo-webhooks
Register the missing webhooks with Loxo. Already-registered webhooks are left alone, so calling this repeatedly is safe.
curl -X POST -u "admin:abcd efgh ijkl mnop" \
https://example.com/wp-json/loxo/v1/loxo-webhooks
Response — 200 OK
{ "message": "3 Webhook Registered." }
GET /wp-json/loxo/v1/loxo-webhooks
Check which of the three webhooks are registered.
Response — 200 OK (all present)
{ "message": "All Webhooks are present." }
Response — 200 OK (some missing)
{
"message": "Missing Webhooks - job.create, job.update.",
"missing": 2
}
DELETE /wp-json/loxo/v1/loxo-webhooks
Remove all webhooks this site registered with Loxo.
Response — 200 OK
{ "message": "3 Webhook Deleted." }
Webhook Event Listener
POST /wp-json/loxo/v1/loxo-event
The receiving end of the webhooks above: this is the callback URL registered with Loxo, and Loxo calls it when a job is created, updated, or deleted. It is documented here so you know what the URL is for — you never need to call it yourself, and it is not a supported surface for pushing your own data in.
Job Expiration
POST /wp-json/loxo/v1/job-expiration
Set the expiration date of a job. PUT is accepted as an alias.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The WordPress post ID of the job (not the Loxo job ID). |
date_expires | string | Yes | Expiration date in Y-m-d format, e.g. 2026-12-31. |
curl -X POST -u "admin:abcd efgh ijkl mnop" \
-d "id=123" -d "date_expires=2026-12-31" \
https://example.com/wp-json/loxo/v1/job-expiration
Response — 200 OK
{
"success": true,
"data": { "date_expires": "2026-12-31" }
}
Note: unlike the other endpoints, a failed call (unknown ID, invalid date) answers { "success": false, "data": false } with HTTP status 200 — check the success field, not the status code.
Job View Tracking
POST /wp-json/loxo/v1/job-view
Increment a job’s view counter. This is the endpoint the plugin’s front end calls on each job page view; it is public — no authentication — and only works while view tracking is enabled in the plugin settings (see Job View Tracking).
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The WordPress post ID of the job. |
Response — 200 OK
{ "success": true }
Errors: 403 disabled — view tracking is turned off · 400 invalid_job — the ID is not a job.
A third 403 can come from WordPress rather than the plugin. The route needs no authentication, but if the request sends an X-WP-Nonce header, WordPress checks it before the route runs and rejects a stale one with rest_cookie_invalid_nonce. The plugin’s own front-end script always sends that header, and the token it uses is baked into the page HTML, so on a page served from a cache older than about a day every view request fails this way. Calling the endpoint yourself, send no nonce header at all rather than an old one.
Data Management
DELETE /wp-json/loxo/v1/cache
Clear all cached Loxo API responses. Harmless — the cache rebuilds on demand.
curl -X DELETE -u "admin:abcd efgh ijkl mnop" \
https://example.com/wp-json/loxo/v1/cache
Response — 200 OK
{ "message": "API Cache cleared." }
DELETE /wp-json/loxo/v1/data
⚠️ Destructive. Deletes every imported job from WordPress — posts, taxonomies, and metadata. There is no undo; the jobs can only be restored by running a fresh synchronization from Loxo.
curl -X DELETE -u "admin:abcd efgh ijkl mnop" \
https://example.com/wp-json/loxo/v1/data
Response — 200 OK
{ "message": "All data deleted." }
Google Indexing
Programmatic control of the Google Indexing API integration — that guide covers creating the service account and credentials; these endpoints drive the integration once it exists.
GET /wp-json/loxo/v1/google-indexing/status
Current state of the integration: configuration, daily quota, submission queue, and recent activity log.
Response — 200 OK
{
"enabled": true,
"configured": true,
"client_email": "[email protected]",
"project_id": "my-project",
"quota": { "used": 12, "limit": 200, "date": "2026-08-09" },
"queue_count": 3,
"log": [ ... ]
}
POST /wp-json/loxo/v1/google-indexing/settings
Save the integration settings.
| Parameter | Type | Required | Description |
|---|---|---|---|
enabled | string | No | yes to enable automatic submission, anything else disables it. |
credentials | string | No | The Google service-account key, as its raw JSON text. |
remove_credentials | boolean | No | true deletes the stored key (and wins over credentials). |
Response — 200 OK
{
"message": "Settings saved.",
"status": { ...same shape as the status endpoint... }
}
POST /wp-json/loxo/v1/google-indexing/test
Test the connection using the stored credentials. No parameters.
Response — 200 OK
{
"message": "Connected as [email protected]. The Google Indexing API connection is working.",
"client_email": "[email protected]"
}
Errors: 400 not_configured — no service-account key saved yet.
POST /wp-json/loxo/v1/google-indexing/submit
Submit a single URL to Google.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The URL to submit. Must belong to this website. |
type | string | No | URL_UPDATED (default) or URL_DELETED to request removal. |
curl -X POST -u "admin:abcd efgh ijkl mnop" \
-d "url=https://example.com/job/senior-developer/" \
https://example.com/wp-json/loxo/v1/google-indexing/submit
Response — 200 OK
{
"message": "URL submitted to Google for indexing.",
"status": { ...same shape as the status endpoint... }
}
Errors: 400 invalid_url / 400 invalid_url_host — missing or foreign URL · 429 quota_exhausted — the daily quota is used up.
POST /wp-json/loxo/v1/google-indexing/submit-all
Queue every published job for submission. URLs are submitted from the queue over time, respecting the daily quota. No parameters.
Response — 200 OK
{
"message": "Queued 24 job URLs for submission to Google.",
"queued": 24,
"status": { ...same shape as the status endpoint... }
}
Errors: 400 not_configured — enable the integration and save a key first.
POST /wp-json/loxo/v1/google-indexing/url-status
Ask Google what it knows about a URL.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The URL to check. Must belong to this website. |
Response — 200 OK
{
"message": "Last update notification received by Google on August 9, 2026 10:30 am.",
"metadata": {
"url": "https://example.com/job/senior-developer/",
"latestUpdate": {
"url": "https://example.com/job/senior-developer/",
"type": "URL_UPDATED",
"notifyTime": "2026-08-09T04:30:12.000Z"
}
}
}
If Google has never seen the URL, the response is { "message": "Google has no record of this URL." }.
DELETE /wp-json/loxo/v1/google-indexing/log
Clear the integration’s activity log. No parameters.
Response — 200 OK
{ "message": "Activity log cleared." }
Related documentation
- Synchronizing Jobs — the plugin’s built-in sync process that most of these endpoints control.
- Webhooks — how to set up and manage real-time job updates.
- Job View Tracking — the plugin feature behind the job-view endpoint.
