Developer Documentation

VSH GMS Inbound API

This API allows approved Garage Management Systems (GMS) to submit vehicle service and invoice records directly to Vehicle Service History. Records submitted through this API appear in the public vehicle history search with a blue-tick verification badge, confirming they were uploaded directly from an invoice.

Bearer Token Auth
Idempotent
Sandbox + Production
v1
Endpoint

Production & Sandbox (same URL)

https://www.vehicleservicehistory.co.uk/functions/gmsServiceRecords

The sandbox and production environments share the same endpoint URL and JSON schema. The environment is determined by your bearer token — a sandbox token writes test data; a production token writes live data. To go live, simply swap your sandbox token for a production token. No URL or payload changes are required.

Authentication

Every request must include a Bearer token in the Authorization header. Tokens are issued by VSH and are unique to each GMS integration. Each token is scoped to a single integration and can only create service records attributed to that integration — it cannot read, update, delete, or access any other VSH data.

Header format

Authorization: Bearer <your-token>

Token properties:

  • Format: vsh_gms_<environment>_<48-hex-chars>
  • Stored as a one-way SHA-256 hash — plaintext is shown only once at creation
  • Revocable and rotatable by VSH at any time
  • Scoped to a single integration — no access to other VSH data
Required Headers
HeaderValueRequired
AuthorizationBearer <token>
Yes
Content-Typeapplication/json
Yes
Request Body — JSON Schema

Required Fields

FieldTypeDescription
registrationstringUK registration plate. Spaces are stripped; case is normalised to uppercase.
service_datestringDate of service in YYYY-MM-DD format. Cannot be in the future.
mileageintegerVehicle mileage at time of service. Must be a non-negative integer.
external_record_idstringYour unique reference for this record/invoice. Used for idempotency — prevents duplicate uploads.

Optional Fields

(may be omitted without error)
FieldTypeDescription
vinstringVehicle Identification Number, if available.
invoice_numberstringInvoice or job reference number.
parts_fittedstringParts fitted or replaced (free text or comma-separated).
work_descriptionstringDescription of the work carried out.
service_typestringOne of: service, mot, repair, inspection.
makestringVehicle make (e.g. Ford).
modelstringVehicle model (e.g. Focus).
colourstringVehicle colour.

No personal data. VSH does not collect or store customer names, addresses, or contact details. Only vehicle and service information is recorded.

Example Request
HTTP Request
POST /functions/gmsServiceRecords HTTP/1.1
Host: www.vehicleservicehistory.co.uk
Content-Type: application/json
Authorization: Bearer vsh_gms_sandbox_a1b2c3d4e5f6...

{
  "registration": "AB12CDE",
  "service_date": "2026-09-15",
  "mileage": 54230,
  "external_record_id": "INV-2026-0001",
  "vin": "WVWZZZ1KZAW000001",
  "invoice_number": "INV-2026-0001",
  "parts_fitted": "Oil filter, Air filter, Sump plug washer",
  "work_description": "Full service including oil and filter change. Brakes inspected - good condition.",
  "service_type": "service",
  "make": "Volkswagen",
  "model": "Golf",
  "colour": "Black"
}
cURL
curl -X POST \
  https://www.vehicleservicehistory.co.uk/functions/gmsServiceRecords \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer vsh_gms_sandbox_a1b2c3d4e5f6..." \
  -d '{
    "registration": "AB12CDE",
    "service_date": "2026-09-15",
    "mileage": 54230,
    "external_record_id": "INV-2026-0001",
    "work_description": "Full service with oil change",
    "service_type": "service"
  }'
Example Responses
201 Created (success)
{
  "success": true,
  "status": 201,
  "message": "Service record created successfully.",
  "data": {
    "record_id": "a3f7c2e1-9b8d-4f2a-8c1e-7d6b5a4f3e2d"
  }
}
422 Unprocessable Entity
{
  "success": false,
  "status": 422,
  "message": "Business validation failed.",
  "errors": [
    { "field": "registration", "message": "Invalid UK registration format" }
  ]
}
409 Conflict (duplicate)
{
  "success": false,
  "status": 409,
  "message": "A record with this external_record_id has already been submitted.",
  "data": { "record_id": "a3f7c2e1-9b8d-4f2a-8c1e-7d6b5a4f3e2d" }
}
HTTP Status Codes
201

Created

Service record accepted and stored. Returns the VSH record_id.

400

Bad Request

Missing required fields, malformed JSON, or wrong data types.

401

Unauthorized

Missing or invalid Bearer token.

403

Forbidden

Token is valid but has been revoked.

409

Conflict

A record with this external_record_id already exists. Returns the existing record_id.

422

Unprocessable Entity

Structure is valid but data fails business validation (bad registration, negative mileage, future date).

429

Too Many Requests

Rate limit exceeded (60 requests per 60 seconds per token).

500

Internal Server Error

Unexpected server-side error.

Validation Rules
  • Registration: must be a valid UK plate format. Spaces are stripped and case is normalised automatically.
  • service_date: must be a valid date in YYYY-MM-DD format and cannot be in the future.
  • mileage: must be a non-negative integer (no decimals).
  • external_record_id: must be unique per integration. Resubmitting the same ID returns 409 with the existing record_id.
  • service_type: if provided, must be one of: service, mot, repair, inspection.
  • Optional fields: may be omitted entirely. If present, must match the stated data type.
Idempotency & Duplicate Submissions

Each request must include an external_record_id — your unique reference for the invoice or service record. VSH uses the combination of your integration ID and this external ID to detect duplicates. If you resubmit the same external_record_id, VSH returns409 Conflictwith the existing VSH record_id, rather than creating a duplicate. This means you can safely retry failed requests without risk of creating duplicate records.

Rate Limits

Each integration is limited to 60 requests per 60 seconds. If this limit is exceeded, the API returns 429 Too Many Requests. Please implement retry-with-backoff in your client. If your integration requires a higher limit, contact VSH.

Sandbox Testing

VSH provides a sandbox environment so you can test your integration end-to-end before going live.

  1. 1
    Obtain a sandbox token. Contact VSH to receive a sandbox bearer token. This token is separate from your production token.
  2. 2
    POST test records to the same endpoint URL using your sandbox token. Records are accepted and stored, but flagged as sandbox data.
  3. 3
    Verify isolation. Search for your test registration on the public VSH site — sandbox records are excluded from public search, so your test data will not appear. This confirms your integration is working without affecting live data.
  4. 4
    Go live. Replace your sandbox token with the production token. The URL and JSON payload remain identical — only the token changes.
Security
  • All traffic is HTTPS only.
  • Tokens are stored as one-way SHA-256 hashes — plaintext is never persisted.
  • Tokens are scoped per integration and cannot access unrelated VSH data.
  • All input is validated server-side before any record is created.
  • Credentials can be revoked or rotated by VSH at any time.
VSH GMS Inbound API · Version 1 · For integration support, contact the VSH team.