Quickstart
This takes about five minutes. You will create a secret key, check it with GET /v1/me and list stock with GET /v1/vehicles.
1. Create a key
API keys are created in the DMS by someone with permission to manage integrations.
- Sign in to the Vehiso DMS (Dealer Management System) at myvehiso.com.
- Go to Administration > Developers.
- Create a secret key. Choose test to work against the shared sandbox dealer, or live to work with your own data.
- Give it the
vehicles:readscope. You can add more later. - Copy the key. It is shown once; Vehiso only stores a hash of it.
The key looks like vh_test_sk_ or vh_live_sk_ followed by two random parts. Keep it on a server, never in browser code or a public repository. See Authentication and API keys for the key types.
Put it in an environment variable for the examples below:
export VEHISO_API_KEY="vh_test_sk_..."
2. Check the key
GET /v1/me works with any scope. It tells you which key you are using and which dealer it acts for.
- curl
- Node.js
- PHP
- Python
curl https://api.vehiso.com/v1/me \
-H "Authorization: Bearer $VEHISO_API_KEY"
const res = await fetch('https://api.vehiso.com/v1/me', {
headers: {Authorization: `Bearer ${process.env.VEHISO_API_KEY}`},
});
const body = await res.json();
if (!res.ok) {
throw new Error(`${res.status} ${body.code}: ${body.message}`);
}
console.log(body.data);
<?php
$ch = curl_init('https://api.vehiso.com/v1/me');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('VEHISO_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status >= 400) {
throw new RuntimeException("{$status} {$body['code']}: {$body['message']}");
}
print_r($body['data']);
import os
import requests
res = requests.get(
"https://api.vehiso.com/v1/me",
headers={"Authorization": f"Bearer {os.environ['VEHISO_API_KEY']}"},
timeout=30,
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {body['code']}: {body['message']}")
print(body["data"])
The answer names the dealer, the key and the user the key acts as:
{
"data": {
"dealer": {"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "name": "Example Motors"},
"key": {
"id": "7c1e9a2b-3d4f-4e5a-8b6c-9d0e1f2a3b4c",
"name": "Stock sync",
"type": "secret",
"environment": "test",
"prefix": "vh_test_sk_4fT9",
"scopes": ["vehicles:read"],
"effective_scopes": ["vehicles:read"],
"expires_at": null
},
"user": {
"id": "2e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"first_name": "Sam",
"last_name": "Jones",
"email": "sam@example-motors.co.uk",
"branch_id": null
},
"app": null,
"scopes_available": ["vehicles:read", "vehicles:write", "branches:read"]
}
}
scopes_available is shortened here. effective_scopes is what the key can use today: a scope whose DMS permission the key's owner has lost stays in scopes but drops out of effective_scopes.
A 401 means the key was not accepted. The code in the response body says why, for example invalid_api_key or api_key_revoked. See Requests and responses.
3. List stock
GET /v1/vehicles needs the vehicles:read scope. Lists are cursor-paginated: ask for up to 100 at a time with limit.
- curl
- Node.js
- PHP
- Python
curl "https://api.vehiso.com/v1/vehicles?limit=10" \
-H "Authorization: Bearer $VEHISO_API_KEY"
const res = await fetch('https://api.vehiso.com/v1/vehicles?limit=10', {
headers: {Authorization: `Bearer ${process.env.VEHISO_API_KEY}`},
});
const {data, meta} = await res.json();
console.log(`Got ${data.length} vehicles, more to fetch: ${meta.has_more}`);
<?php
$ch = curl_init('https://api.vehiso.com/v1/vehicles?limit=10');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('VEHISO_API_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
echo count($body['data']) . " vehicles, more to fetch: " . var_export($body['meta']['has_more'], true) . "\n";
import os
import requests
res = requests.get(
"https://api.vehiso.com/v1/vehicles",
params={"limit": 10},
headers={"Authorization": f"Bearer {os.environ['VEHISO_API_KEY']}"},
timeout=30,
)
body = res.json()
print(len(body["data"]), "vehicles, more to fetch:", body["meta"]["has_more"])
The response has the vehicles under data and the paging state under meta:
{
"data": [
{
"id": "5f0c6a8e-2d41-4f7b-9a53-1f0e8c2b7d19",
"external_id": "STK-1042",
"registration": "AB12CDE",
"status": "IN_STOCK",
"make": "Volkswagen",
"model": "Golf",
"mileage": 32150,
"price": {"amount": 1499500, "currency": "GBP"},
"updated_at": "2026-09-27T14:02:11Z"
}
],
"meta": {
"next_cursor": "eyJpdiI6...",
"has_more": true
}
}
Each vehicle carries many more fields than shown here; List vehicles lists them all. To fetch the next page, send meta.next_cursor back as ?cursor=. Pagination and syncing covers this in full.
Next steps
- Learn how keys, scopes and the key owner interact: Authentication and API keys.
- Push stock from your own system: Batch stock and image upload.
- Get notified of changes: Webhooks and events.