Documentation
Service VIN developer & AI platformGetting startedAuthenticationPaginationIdempotencyRate limitsErrorsWebhooks & signature verificationConnecting ClaudeRecipesMCP servers & the Claude connectorREST resource referenceCapability indexCustomers capabilitiesVehicles capabilitiesLeads capabilitiesWarranties capabilitiesQuotes capabilitiesInvoices capabilitiesPayments capabilitiesServices capabilitiesJobs capabilitiesCalendar capabilitiesScheduling capabilitiesStaff capabilitiesInventory capabilitiesComms capabilitiesTasks capabilitiesShop capabilitiesDocuments capabilitiesKnowledge capabilitiesReports capabilitiesBooking capabilitiesForms capabilitiesMarketing capabilitiesReviews capabilitiesAutomations capabilitiesIntegrations capabilitiesChangelogSearch
Guide
Errors
Success is an envelope and so is failure. Switch on `error.code`; the messages are written for people and may change.
Success
{
"data": "…",
"meta": {
"next_cursor": null
}
}Failure
{
"error": {
"code": "unauthorized",
"message": "Invalid or revoked API key."
}
}Switch on error.code rather than parsing error.message: the codes are stable, the messages are written for humans and may change.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request body was not valid JSON. |
| 401 | unauthorized | Missing, invalid, revoked, or expired API key. |
| 403 | insufficient_scope | A read-only key was used on an endpoint that writes. |
| 403 | org_suspended | The account behind the key is suspended. |
| 402 | plan_lapsed | The account behind the key has no active subscription (trial ended, canceled, or payment failed). |
| 403 | plan_required | The shop's plan does not include this feature. |
| 404 | not_found | No such resource in this shop. |
| 409 | conflict | A duplicate already exists, or a per-shop limit is reached. The message names the id or the limit. |
| 422 | validation_error | A field failed validation. The message names the field. |
| 429 | rate_limited | Over the per-key rate limit. |
| 500 | internal_error | Our fault. Safe to retry. |
| 501 | not_implemented | The endpoint exists but is deliberately not offered. The message says what to do instead. |
`404 not_found` on a capability you can see documented here means the feature is not enabled for that account. It is deliberately the same answer an unknown id gets — a distinguishable answer would leak the existence, the name and the price of something the account could not have at any price.
`422 validation_error` names the field, not the constraint. A message that reads "Too big: expected array to have <=6 items" names none of the fourteen arrays a request might hold; ours names the one you got wrong.
Every refusal is in the ledger
A refused call is audited exactly like a successful one — who, which surface, which capability, the outcome and the duration, never the argument values themselves. "What did this key TRY to do" is the more interesting question, and a ledger that only records successes cannot answer it.