Documentation · Appendices

REST Endpoint Reference

This appendix lists the REST API routes registered by the ADP Car Market Hub plugin under the as24ci/v1 namespace.

When to use this document

Use this reference when you need to call a plugin endpoint, when you are diagnosing unexpected 403/404 responses, or when you are documenting an integration. For the conceptual description of each endpoint, see REST API Endpoints.

Overview

All routes registered by the plugin use the WordPress REST API and share the namespace as24ci/v1. The full URL of any endpoint is the WordPress REST root followed by the route, typically https://example.com/wp-json/as24ci/v1/....

The endpoints fall into five groups:

  1. Public vehicle data (/vehicles, /vehicles/{id}) — disabled by default; gated by as24ci_rest_api_enabled.
  2. Favorites helper (/favorites) — used by the front-end favorites page.
  3. Analytics tracking (/analytics/track) — used by the front-end script.
  4. Cron import trigger (/cron-import) — token-protected; used by external schedulers.
  5. License refresh signal (/license-refresh-signal) — used by the API Platform to ask the site to re-validate its license.

Endpoint summary

RouteMethodAuthAlways registered?
/as24ci/v1/vehiclesGETNone (public)No — only when as24ci_rest_api_enabled is '1'.
/as24ci/v1/vehicles/{id}GETNone (public)No — same gating as above.
/as24ci/v1/favoritesPOSTNone (public)Yes.
/as24ci/v1/analytics/trackPOSTNone (public)Yes.
/as24ci/v1/cron-importGETBearer tokenYes. Returns 403 until a token is configured.
/as24ci/v1/license-refresh-signalPOSTSignal-only trust model (handled inside callback)Yes.

GET /as24ci/v1/vehicles

Paginated, filterable list of imported vehicles whose post status is publish.

Query parameters:

ParameterTypeDefaultNotes
pageinteger ≥ 11Page number.
per_pageinteger 1–10010Items per page.
makestringExact match against the make meta key.
modelstringExact match against the model meta key.
fuel_typestringLIKE match against the fuel type meta key.
year_min, year_maxintegerNumeric range against _as24ci_year.
price_min, price_maxnumericNumeric range against _as24ci_price.
orderbydate, price, mileage, titledateSort field.
orderasc, descdescSort direction (case-insensitive).

Response (shape):

{
  "vehicles": [
    {
      "id": 0, "title": "", "url": "", "image": "",
      "make": "", "model": "", "year": 0, "price": 0,
      "currency": "EUR", "mileage": 0, "condition": "",
      "fuel_type": "", "transmission": "", "body_type": "",
      "color": "", "doors": 0, "horse_power": 0, "vin": "",
      "listing_id": ""
    }
  ],
  "total": 0,
  "pages": 0,
  "page": 1,
  "per_page": 10
}

The image field is the medium-large size of the featured image (empty string when none). The currency field falls back to as24ci_default_currency when no per-vehicle currency is stored.

GET /as24ci/v1/vehicles/{id}

Full details for a single vehicle.

  • Path parameter: id — positive integer; validated and cast through absint.
  • Auth: none (public). Same gating as the list endpoint.
  • Response: all fields from the list response plus description, images (array of attachment URLs at large size, combining manual and imported images and falling back to the featured image), equipment_standard, equipment_optional and seller.
  • Errors: 404 as24ci_vehicle_not_found when the post does not exist, is not the as24ci_car CPT, or is not published.

POST /as24ci/v1/favorites

Hydrates the visitor's favorites with current vehicle data for IDs stored in browser local storage.

  • Auth: none (public). Always registered.
  • Body: JSON object with ids — an array of post IDs. Sanitised to a unique list of positive integers; capped at 50 IDs per request.
  • Response: { "vehicles": [ ... ] }.
  • Notes: Only published vehicles are returned. Posts the visitor no longer has access to (deleted, draft, wrong post type) are silently omitted.

POST /as24ci/v1/analytics/track

Receives analytics events from the front-end tracking pixel.

  • Auth: none (public). Always registered.
  • Body parameters:
  • post_id — integer ≥ 0. Default 0.
  • event_type — one of view, view_archive, view_compare, view_favorites, filter_search, contact_open, lead_sent.
  • extra_data — optional sanitised string. For filter_search, must be a JSON object containing the active filter key/value pairs.
  • Response: { "tracked": true } on success, or { "tracked": false } with HTTP 400 when the event requires a vehicle post that does not exist or is unpublished.
  • Notes: Intentionally permissive so anonymous visitors can send events. Do not rely on it for authoritative business data.

GET /as24ci/v1/cron-import

Token-protected endpoint that runs the shared import routine. Delegates to the same Scheduler::run_import() method used by the WP-Cron hook and the manual "Trigger now" admin button.

  • Auth: bearer token. Provide the token via either the HTTP header Authorization: Bearer <token> (preferred — keeps the token out of access logs) or the ?token=<token> query parameter. Comparison uses hash_equals() to mitigate timing attacks.
  • Token storage: as24ci_cron_token option. Generate or rotate it from Import & Limits in the plugin admin.
  • Responses:
  • 403 when no token is configured or the supplied token does not match.
  • 200 with { "success": true, "message": "...", "counts": { ... } } on a successful run.
  • 429 with success: false when another import is already running and the runner declined to start a second one.
  • 500 when the runner threw an exception.
  • Side effect: A successful authentication updates as24ci_last_external_cron_run, which the System & Help tab uses to confirm that the external cron is reaching the site. Visiting any URL with ?as24ci_cron=1 also updates this timestamp via the heartbeat hook on init.

Example external cron invocation (placeholder — substitute your own host and a generated token):

0 * * * * curl -fsS -H "Authorization: Bearer YOUR_TOKEN" \
  "https://example.com/wp-json/as24ci/v1/cron-import?as24ci_cron=1"

POST /as24ci/v1/license-refresh-signal

Lightweight signal endpoint that lets the API Platform ask the site to re-validate its license out of band (for example after a plan change). Registered unconditionally so the platform can always reach it; it is not gated behind the public vehicle REST API option.

  • Auth: signal-only trust model. Authentication is handled inside the callback rather than by a permission_callback; the request must be JSON and is validated against the expected signal shape.
  • Body: JSON object. Safe, non-secret correlation fields (request_id, event) are echoed back for tracing only.
  • Responses:
  • 405 method_not_allowed when the request is not POST.
  • 400 invalid_content_type when the body is not JSON, or 400 invalid_json when the body cannot be parsed.
  • 200 when the signal is accepted.
  • Owner: AS24CI\License_Refresh_Signal.

Operational notes

  • The public vehicle endpoints execute standard WP_Query calls and honour normal WordPress object caching. Repeated identical requests benefit from the post and post-meta caches.
  • Numeric filters add to a meta_query. On large catalogues, ensure the underlying meta keys are indexed at the database level if you expect heavy traffic. Verify the indexing strategy in the current plugin version before publishing.
  • The list endpoint applies update_postmeta_cache() on the returned posts to keep response times predictable.
  • The favorites endpoint hard-caps each request at 50 IDs to prevent abuse.
  • The cron import endpoint sets nocache_headers() so caching proxies do not interfere with scheduled runs.
  • Pretty permalinks are recommended for path-style REST URLs. With plain permalinks, the endpoints are still reachable via ?rest_route=.

Troubleshooting

  • /vehicles returns 404. The public API is disabled. Set as24ci_rest_api_enabled to '1' in Settings → SEO & Integrations (or via WP-CLI / update_option).
  • /cron-import returns 403. Either no token is configured (as24ci_cron_token empty — the response message confirms this) or the supplied token does not match. Generate a new token from the admin and retry.
  • /cron-import returns 429. Another import is already running and a lock prevents a second concurrent run. Wait for the current run to finish.
  • Empty vehicles array on the list endpoint with no filters. No vehicles are published, or the catalogue has not been imported yet. Check the Import & Limits screen and the import logs.
  • HTTP 400 on /analytics/track. The event requires a published vehicle post but post_id references a draft, deleted or non-vehicle post.