Site API reference
The endpoints a dealer's own website calls: shop, vehicles, one vehicle, and leads. Authentication, limits and errors.
Base address: https://dealer.wheewise.com/api/site/v1. A machine-readable description is always current at openapi.json.
Authentication
- Send the site key in the
X-Wheewise-Site-Keyheader (or as?key=on aGET). - From a browser, the request's origin must be on the allowed list; otherwise the answer is
403and the browser blocks it. A server call without anOriginheader works with the key alone. - Preflight (
OPTIONS) requests are answered for any origin. OnlyGET,POSTandOPTIONSare allowed; credentials and cookies are never used.
GET /shop
The shop's public details: name, city, address, bio, business_hours, map_link, logo_url, cover_photo_url, hero_image_url, gallery_urls, live_vehicles, wheewise_page.
GET /vehicles
The dealer's published vehicles only (drafts, paused and sold ones never appear).
| Query | Meaning |
|---|---|
limit (1 to 50, default 20), offset | Paging. |
q | Searches make, model and variant. |
make, category, fuel | Filters. fuel is PETROL, DIESEL, CNG, ELECTRIC or HYBRID. An unknown category or fuel returns 400. |
min_price, max_price, min_year | Ranges. |
sort | newest (default), price_asc, price_desc, year_desc. |
Returns { "total": 31, "vehicles": [ … ] }. Each vehicle has id, slug, url, make, model, variant, year, fuel_type, transmission, odometer_km, asking_price (rupees), city, description, photo_urls (the first is the cover), finance_available, color, body_type, seating_capacity, cubic_capacity_cc, horsepower_bhp, insurance_valid_months, puc_valid_months, created_at, updated_at. Costs, margins, registration and chassis numbers are never included.
GET /vehicles/{id}
One published vehicle, by id or slug. 404 if it is not published.
POST /leads
Sends an enquiry or a test-drive request to the dealer. It appears under Leads in the dealer app and the dealer is notified.
{
"name": "Ravi Kumar",
"phone": "+91 98765 43210",
"email": "[email protected]",
"message": "Is it still available?",
"vehicle_id": "<an id from /vehicles>",
"kind": "TEST_DRIVE",
"preferred_at": "2026-11-01T10:30:00+05:30",
"website": ""
}name,phoneandemailare required.kindisENQUIRY(default) orTEST_DRIVE.TEST_DRIVEneeds avehicle_idof a published vehicle and apreferred_atthat is in the future and within 90 days (ISO 8601 with an offset).websiteis a spam trap: add a hidden form field with this name and leave it empty.- The same person asking about the same vehicle (same kind) twice in a day is stored once.
Limits and errors
| Status | Meaning |
|---|---|
| 400 | A field is missing or invalid; error says which. |
| 401 | No site key, or the key was replaced. |
| 403 | The website is not on the allowed list. |
| 404 | Vehicle or shop not available. |
| 413 | Request body over 4 KB. |
| 429 | Too many requests (per visitor, per key, or per shop per day). |
Errors look like { "error": "message" } and are written to be shown to a visitor. GET responses may be cached by the browser for 30 seconds.
A minimal client
const API = "https://dealer.wheewise.com/api/site/v1";
const SITE_KEY = "wws_...";
export async function wheewise(path, init = {}) {
const res = await fetch(API + path, {
...init,
headers: { "X-Wheewise-Site-Key": SITE_KEY, "Content-Type": "application/json", ...init.headers },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error || "Request failed");
return body;
}
export const getVehicles = (params = {}) => wheewise("/vehicles?" + new URLSearchParams(params));
export const sendLead = (lead) => wheewise("/leads", { method: "POST", body: JSON.stringify(lead) });