Overview
This API is for the developer of a garage admin platform that runs several workshops on the same software. One partner organisation can cover up to eight (or more) garages. Each garage is a site. You can mint a key per site, or one organisation key that sends X-Hawkeye-Site on every call.
Jobs keep the platform’s own field names and stages: Job Pack, Inspection, Customer Approval, Quote Approved, Repairs Started, Repairs Complete, Invoice Ready, Job Completed. When a job is completed, BE Systematic stores the asset, the reason for work, the cause and the rectification in that garage’s vector store. The next similar job gets a guided diagnosis from those recorded fixes, with a confidence score. Part numbers and torque figures are never invented.
If the workshops agree, they can opt in to shared knowledge so a fix learned at one garage can be cited at the others. It is off until you switch it on. Other customers are never searched.
The platform does not need a public API of its own. Day one can be CSV import of customers, vehicles and invoices, plus a Sage 50 UK export of book-out lines. For live diagnosis, push the appointment as you already store it.
Examples on this page use fictitious sandbox data only: addresses at example.test and registrations ending TST. No live garage is contacted and no real customer data is included.
Production base URL: https://hawkeye.brownhawke.engineering/api/machine-viewer/v1
Staging (behind Cloudflare Access): https://hawkeye-next.brownhawke.engineering/api/machine-viewer/v1
Also available: OpenAPI 3.1, Postman collection, curl walkthrough.
Authentication
Every call (except minting a sandbox session) sends a key the customer created, or one minted for a site or the organisation:
Authorization: Bearer hkmvp_...
With an organisation-wide key, also send the site:
X-Hawkeye-Site: garage-01
site_id in the JSON body or query string is accepted as well. A site-scoped key cannot act on a different site (403 site_denied). An organisation key without a site is 400 site_required.
HTTPS only. Idempotency-Key on any POST; the first response is kept 24 hours. On these garage-platform routes a repeat with the same key and body returns that response as 200 with "created": false and "idempotent_replay": true.
Quick start in 5 minutes
- On staging, mint a sandbox session (no live data is used):
curl -sS -X POST https://hawkeye-next.brownhawke.engineering/api/machine-viewer/v1/connectors/garage-platform/sandbox/session \ -H "Content-Type: application/json" -d '{}'The response includesapi_key(shown once), eight site ids, and a seeded history (a water pump job onAB01TSTat garage-01, a clutch job at garage-02, and so on). - Push a new Inspection job in the platform’s own fields (body as in Examples).
- Read
diagnosis.suggestionsandwork_order.guide. The sandbox already has a completed overheating job, so the new one should cite it. - When the repair is signed off,
POST /job-cards/apt_demo_new/closewith cause and rectification. That write is what the next similar job will retrieve.
Sites and keys
Create the organisation, add sites, then mint keys:
POST /connectors/garage-platform/org
POST /connectors/garage-platform/sites
{"site_id":"garage-01","name":"North Workshop","portal_base":"https://platform.example.test/sites/garage-01"}
POST /connectors/garage-platform/sites/garage-01/keys
POST /connectors/garage-platform/org-key
POST /connectors/garage-platform/shared-knowledge {"enabled": true}
Shared knowledge is off by default. Switching it on only shares completed jobs among sites in this organisation.
Knowledge loop
- On completion the asset (registration or asset number), reason for work, cause and rectification are written into the garage’s vector store, keyed by that asset or vehicle. The same record is updated, never duplicated, when you send the same
appointment_idagain. - On a new job BE Systematic returns a guided diagnosis: similar past fixes, citations, and a confidence score. The work-order guide adds manufacturer data from uploaded manuals when you have it, otherwise a generic library. Lines that look like a torque, capacity or part number are dropped from any generated guide text unless they came from a cited record or manual page.
Endpoint reference
| Method | Path | Purpose |
|---|---|---|
| POST | /connectors/garage-platform/sandbox/session | Seed fictitious data and issue a key (staging / when the sandbox flag is on) |
| GET | /ping | Check a key |
| GET | /connectors/garage-platform | Profile, stage map, organisation |
| GET/POST | /connectors/garage-platform/org | Read or create the organisation |
| POST | /connectors/garage-platform/sites | Add a garage |
| POST | /connectors/garage-platform/sites/{id}/keys | Site-scoped key |
| POST | /connectors/garage-platform/org-key | Organisation key |
| POST | /connectors/garage-platform/shared-knowledge | Opt in or out |
| POST | /connectors/garage-platform/jobs | Upsert a job; diagnosis + guide |
| POST | /job-cards/{appointment_id}/close | Record the fix |
| POST | /connectors/garage-platform/imports | CSV import (dry_run supported) |
| GET | /connectors/garage-platform/sage-export | Sage 50 UK CSV of book-outs |
| GET/POST | /connectors/garage-platform/sage-settings | Nominal and VAT codes |
| GET/POST | /callback | Signed webhook (see below) |
Job stages and statuses
| Platform stage or status | status | hold | workflow_stage |
|---|---|---|---|
| Job Pack, Pending, Confirmed | open | job_pack | |
| Inspection | open | inspection | |
| Customer Approval, Awaiting Approval | open | awaiting_authorisation | customer_approval |
| Quote Approved | open | quote_approved | |
| Repairs Started, In Progress | open | repairs_started | |
| Repairs Complete | closed | repairs_complete | |
| Invoice Ready, Invoiced | closed | invoice_ready | |
| Job Completed, Completed | closed | job_completed | |
| Cancelled | closed | cancelled |
Priorities: Urgent, Normal, Fit In.
Example request and response
POST /api/machine-viewer/v1/connectors/garage-platform/jobs
Authorization: Bearer hkmvp_...
Idempotency-Key: apt_demo_new-create
Content-Type: application/json
{
"appointment_id": "apt_demo_new",
"job_number": "JS-DEMO-1",
"workflow_stage": "Inspection",
"priority": "Urgent",
"appointment_date": "2026-11-16",
"appointment_time": "09:30",
"vehicle_registration": "AB01TST",
"vehicle_year": "2019",
"vehicle_make": "Ford",
"vehicle_model": "Focus",
"colour": "Blue",
"fuel_type": "Petrol",
"engine_capacity": "1.0",
"task_description": "Engine overheating, coolant loss",
"internal_notes": "Warning light on after a short run. Example.test demo job."
}
{
"ok": true,
"created": true,
"job_card": {
"external_id": "apt_demo_new",
"external_url": "https://platform.example.test/sites/garage-01/jobsheet?id=apt_demo_new",
"status": "open",
"workflow_stage": "inspection",
"priority": "urgent",
"fault": "Engine overheating, coolant loss"
},
"diagnosis": {
"status": "ready",
"confidence_label": "high",
"suggestions": [
{
"rectification": "Replaced water pump and coolant",
"causes": [
"Water pump bearing failed"
],
"citations": [
"JC-XXXXXX"
],
"times_used": 1,
"times_held": 1,
"held_rate": 1.0
}
],
"figures": "Part numbers and torque or capacity figures are only those recorded on cited job cards or the customer's manuals. Nothing is invented."
},
"work_order": {
"has_guide": true
}
}
Customer contact fields may be sent; they are discarded. appointment_id is the stable external id and becomes a deep link {portal_base}/jobsheet?id={appointment_id} when the site has a portal base.
Webhooks
Register a public https URL with POST /callback. The signing secret is returned once. Default events are diagnosis.ready and diagnosis.failed. job.guide.ready stays off until you list it:
{"url":"https://platform.example.test/hooks/machine-mate",
"events":["diagnosis.ready","diagnosis.failed","job.guide.ready"]}
Deliveries are HMAC-SHA256 signed (Hawkeye-Signature: t=<unix>,v1=<hex> over <t>.<raw body>), up to three tries. Nothing is emailed or texted.
Errors
Errors are {"ok": false, "error": {"code", "message"}, "request_id"}.
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or revoked key |
| 403 | module_off | BE Systematic is not on for this account, or the sandbox is off |
| 403 | site_denied | This key cannot act on that site |
| 400 | site_required | An organisation key needs X-Hawkeye-Site |
| 400 | invalid_request / invalid_json | Fix the body |
| 404 | not_found | Unknown job, site or route |
| 409 | idempotency_key_reused / idempotency_in_progress | See the Partner API guide |
| 429 | rate_limited | Wait Retry-After seconds |
| 500 | internal_error | Retry with the same Idempotency-Key |
Rate limits
60 requests a minute per key by default, up to 600 (set by the customer). JSON bodies up to 256 KB. Idempotency records are kept 24 hours. There is no IP allowlist; verify webhook signatures instead.
Versioning
- The major version is in the path (
/v1). Within v1 we only make additive changes: new optional request fields, new response fields, new error codes, new endpoints, new template versions. Ignore fields you don't know. - A breaking change ships as
/v2;/v1keeps working for at least 6 months after/v2is announced (proposed policy, to be confirmed by Hawkeye before the first external partner goes live). - Job-card templates are versioned separately (semver); send
template_versionto pin one.
Data location
Where. Hawkeye runs on Cloudflare (edge and containers) with a managed Postgres store. No China-hosted providers are used.
Sandbox
On staging (or wherever HAWKEYE_GARAGE_PLATFORM_SANDBOX=1), POST /connectors/garage-platform/sandbox/session resets a dedicated sandbox account (sandbox@example.test), creates eight sites (garage-01 … garage-08), seeds three completed jobs and three vehicles, opts in to shared knowledge, and returns a garage-01 key and an organisation key. It is off unless that switch is set, so production has no sandbox.
CSV import and Sage export (day one, no code)
POST /connectors/garage-platform/imports with kind customers, vehicles, invoices or jobs. Header names are matched loosely. dry_run: true returns a preview and writes nothing. Re-importing the same external id updates the row; nothing is deleted. Customer names, emails, phones and addresses are not stored — only an external id and a Sage or fleet account reference.
GET /connectors/garage-platform/sage-export returns book-out (stock issue) lines as a Sage 50 Accounts UK audit-trail CSV. Set labour, parts and other nominal codes and VAT codes with POST /connectors/garage-platform/sage-settings before going live. Hawkeye does not upload the file to Sage or email it.