Home Features Pricing App AI Advisor Docs Compare About Training Contact Log In Get an API key
Developersv1.0.0-rc.6
Browse the guides
Developers/Working with the API

Requests & Responses

Typed ids, decimal-string money, UTC instants, wall-clock appointment times, and the object/list envelopes.

Objects

Every resource has id and object. Ids are typed and opaque: a prefix names the resource type, so a vehicle id in a customer slot is rejected as invalid_id before any lookup.

Prefix Resource Prefix Resource
shop_ shop inv_ invoice / credit note
cus_ customer pay_ payment
veh_ vehicle item_ inventory item
appt_ appointment cj_ canned job
ro_ repair order tech_ technician
job_ job (line item) task_ task
part_ / lab_ part / labor entry whe_ / evt_ webhook endpoint / event

Ids are stable for the life of the record. Never parse them.

Money

Amounts are decimal strings"129.99", never floats — with the currency named alongside ("currency": "CAD"). The shop's currency comes from GET /v1/shop; every monetary object repeats it. Do the maths in decimal types.

Dates and times

  • Response instants (created_at, updated_at, posted_at, …) are RFC 3339 in UTC with a Z suffix: 2026-09-01T14:03:27Z. Instant request filters/fields require either Z or an explicit numeric offset; naive datetimes are rejected.
  • Appointments are wall-clock: date (2026-09-14) and exact minute time (09:30, no seconds or zone) in the object's IANA timezone. A DST-gap time is rejected. A repeated fall-back time requires utc_offset such as -04:00 or -05:00. Responses include the resolved UTC starts_at.
  • Dates on financial documents (invoice_date, payment_business_date) are the shop's business dates.

Requests

  • JSON bodies with Content-Type: application/json; unknown fields are rejected (invalid_request with param).
  • PATCH operations are presence-aware: omitted means unchanged. Explicit null clears only documented nullable fields; it is rejected for required/non-clearable fields. false, 0, [], and "" are values, not omission. An empty PATCH is 400 no_changes.
  • Object references in bodies use public ids ("customer_id": "cus_…").
  • Body size is capped at 1 MB.

Response envelopes

A single resource is returned bare. Lists use:

{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "eyJ…" }

Application errors and failures generated by Shop Commander's owned Nginx edge use one shape — see Errors. Uncontrolled network intermediaries can fail before reaching that edge, so retain a fallback for a missing or unreadable JSON body.

Headers on application responses

Header Meaning
X-Request-Id req_… — quote it when contacting support; the shop can trace it in its activity log
RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset Current budget — see Rate limits
Cache-Control: no-store Responses are never cacheable

Owned-edge throttling includes Retry-After but deliberately omits the three RateLimit-* integration-quota headers. Edge-generated envelopes have request_id: null because the request did not reach the application logger.

Sensitive fields

Fields the integration's scopes do not cover are redacted, not omitted: a customer read without customers.read is not possible at all; RO/job/part/labor/canned-job sale pricing needs pricing.read; and acquisition cost needs inventory.cost.read. A denied field is null and its JSON pointer appears in redacted_fields. Treat that null as "not visible to you", not zero.

The OpenAPI field itself declares this rule with x-field-visibility, and each affected operation summarizes it in x-conditional-scopes. These are field capabilities, not operation gates: unlike x-required-scopes, their absence must never prevent the request.

Consistency rules you can rely on

  • Additive changes only within a version: new response fields and extensible string values can appear; nothing is renamed or removed (see Versioning).
  • Workflow state enums include unknown; raw future internal values are never exposed. Treat unknown as an explicit prompt to refresh/report, not as another known state.
  • Every write returns the full resulting object, so you never need a follow-up GET to learn what you changed.