https://dash.lockii.app/api/v1
Create an API key in Settings → Integrations → API.
For apps looking to integrate with Lockii you can request a client ID for use in an OAuth based integration
Method
Example
Header
x-api-key: your_api_key
Bearer token
Authorization: Bearer your_api_key
Query string
?api_key=your_api_key
Lockii uses prefixed IDs. Generate new IDs with a UUID v7 suffix:
Resource
Format
Example
Booking
order_<uuid>
order_01923abc-...
Customer
customer_<uuid>
customer_01923abc-...
ect
ect_<uuid>
ect_Xxxxxxx-...
Work order
maintenance_<uuid>
maintenance_01923abc-...
Part
maintenance_schedule_<uuid>
maintenance_schedule_01923abc-...
Issue report
issue_report_<uuid>
issue_report_01923abc-...
Meter
meter_<uuid>
meter_01923abc-...
All date/time fields are Unix milliseconds (UTC) unless noted otherwise.
All prices and amounts are in cents (e.g. $50.00 = 5000).
GET endpoints accept parameters as query strings. Nested objects and arrays can be passed as JSON strings:
GET /booking?status=active&dateRange={"from":1711270800000,"to":1711357200000}
Search bookings
GET /booking
Returns a filtered list of bookings with customer, location, company, and order line details.
Query parameters:
Parameter
Type
Default
Description
limit
number
15
Maximum results to return
status
string
all
all, active, upcoming, returned, or cancelled
orderBy
string
number
Sort field: createdAt, number, startHireDate, endHireDate, priceInCents
dateRange
object
—
Hire window overlap filter: { "from": number, "to": number } (Unix ms)
createdAtRange
object
—
Created-at filter: { "from": number, "to": number }
totalRange
object
—
Price filter in whole dollars: { "min": number, "max": number }
productID
string
—
Filter to bookings containing this product
stockID
string
—
Filter to bookings containing this stock row
categoryID
string
—
Filter to bookings with products in this category
locationID
string
—
Filter to bookings at this location
minEndHireDate
number
—
Bookings ending on or after this Unix ms timestamp
paymentStatuses
array
—
["paid"], ["unpaid"], or both
Example:
GET /booking?status=active&limit=10&locationID=location_abc123
Response: Array of booking objects, each including related customer, location, company, and orderLines (with product and stock).
Get booking
GET /booking/:id
Returns the full booking page query — the same data shown in the booking editor.
Path parameter: id — booking/order ID
Response includes: customer, location, stock, company, payments, coupon, services, changeRequests, orderLines (with product, reservation, stock), reservations, messages, hireQuizResponses, activityLogs.
Example:
GET /booking/order_abc123
Create change request
POST /booking/change-request
Create and apply a booking change. Evaluates policy, pricing, and availability. For paid changes, Lockii attempts to charge the customer's saved card first and falls back to emailing a payment link.
Body:
{ "order_id": "order_abc123", "data": { "startHireDate": 1711270800000, "endHireDate": 1711357200000, "locationID": "location_xyz", "lineItems": [ { "productID": "product_abc", "quantity": 2 } ], "status": "cancelled" }, "approval_mode": "charge_and_apply", "cancellation_refund_percent": 100 }
Field
Type
Required
Description
order_id
string
Yes
Internal booking ID
data
object
Yes
Requested changes — only include fields you want to change
data.startHireDate
number
No
New start time (Unix ms)
data.endHireDate
number
No
New end time (Unix ms)
data.locationID
string
No
New pickup/return location
data.lineItems
array
No
Replacement line items: { productID, quantity }
data.status
string
No
Set to "cancelled" to cancel the booking
approval_mode
string
No
send_to_customer, charge_and_apply (default for paid changes), or apply_now (waive payment — use only when customer has agreed)
cancellation_refund_percent
number
No
Refund percentage for cancellations (0–100). Defaults to 100
Manual pickup
POST /booking/:id/manual-pickup
Manually mark a booking as picked up. Records the reason and writes the manual pickup quiz response.
Body:
{ "id": "order_abc123", "reason": "Customer collected item in person" }
Field
Type
Required
Description
id
string
Yes
Booking ID (must match path :id)
reason
string
Yes
Reason for manual pickup
Response:
{ "success": true, "id": "order_abc123" }
Manual return
POST /booking/:id/manual-return
Manually mark a booking as returned. Updates reservations, logs activity, and sends return webhooks.
Body: Same shape as manual pickup (id, reason).
Response:
{ "success": true, "id": "order_abc123" }
Refund payment
POST /payment/:id/refund
Refund a paid payment. Stripe-backed payments are refunded in Stripe; manual card payments are adjusted in Lockii.
Body:
{ "id": "payment_abc123", "amount": 5000 }
Field
Type
Required
Description
id
string
Yes
Payment ID
amount
number
Yes
Refund amount in cents (must be positive)
Send payment link
POST /payment-link
Create a Stripe payment link for a booking and store it as a payment record.
Body:
{ "orderID": "order_abc123", "amount": 10000, "id": "payment_abc123", "companyID": "company_xyz" }
Field
Type
Required
Description
orderID
string
Yes
Booking to request payment for
amount
number
Yes
Amount to request in cents
id
string
No
Payment ID. Defaults to a generated payment_<uuid>
companyID
string
No
Defaults to authenticated company
Response: Payment row including paymentData.payment_link_url.
List customers
GET /customer
Query param
Type
Default
Description
status
string
all
all, current (on hire now), recent (booked in last 30 days), new (created in last 30 days), unverified
limit
number
15
Maximum results
Search customers
GET /customer/search?query=john
Query param
Type
Required
Description
query
string
Yes
Search by name, last name, email, or phone
Returns up to 5 matches.
Get customer
GET /customer/:id
Returns a single customer record.
Get customer page
GET /customer/:id/page
Returns customer profile with related non-pending bookings (including location, stock, order lines).
Create customer
POST /customer
Body:
{ "id": "customer_01923abc-def4-7890-abcd-ef1234567890", "name": "Jane", "lastName": "Smith", "email": "[email protected]", "phone": "0412345678", "phoneCode": "+61", "address": "123 Main St", "city": "Sydney", "state": "NSW", "zip": "2000", "country": "AU" }
Field
Type
Required
Description
id
string
Yes
Customer ID (customer_<uuid>)
name
string
No
First name. Defaults to ""
lastName
string
No
Last name. Defaults to ""
email
string
No
Email address
phone
string
No
Phone number
phoneCode
string
No
Country/area code
address, city, state, zip, country
string
No
Address fields
companyID
string
No
Defaults to authenticated company
stripeCustomerID
string
No
Stripe customer ID if linked
Update customer
POST /customer/:id
Same fields as create — all optional except id. Only include fields you want to change.
Delete customer
DELETE /customer/:id
Body:
{ "id": "customer_abc123" }
Block customer
POST /customer/:id/block
Body:
{ "id": "customer_abc123", "reason": "Repeated no-shows" }
Unblock customer
POST /customer/:id/unblock
Body:
{ "id": "customer_abc123" }
Manually verify customer
POST /customer/:id/manual-verify
Body:
{ "id": "customer_abc123", "identityLink": "https://...", "identityExpiresAt": 1742800800000 }
Field
Type
Required
Description
id
string
Yes
Customer ID
identityLink
string
No
Supporting verification link
identityExpiresAt
number
No
Expiry Unix ms. Defaults to one year from now
Generate verification link
POST /customer/:id/verification-link
Body:
{ "customer_id": "customer_abc123", "send_email": true }
Field
Type
Required
Description
customer_id
string
Yes
Customer ID
send_email
boolean
No
Email the link to the customer. Defaults to false
Search products
GET /product
Query param
Type
Default
Description
categoryID
string
—
Filter by category
nameSearch
string
—
Filter by product name (partial match)
excludeId
string
—
Exclude a product ID
limit
number
—
Maximum results
withStock
boolean
false
Include non-archived stock rows
Get product
GET /product/:id
Query param
Type
Default
Description
activeOnly
boolean
true
Exclude archived products
Returns product with category, pricingTemplate, and optionally stock.
Create product
POST /product
Body:
{ "id": "product_01923abc-def4-7890-abcd-ef1234567890", "name": "Kayak Single", "description": "Single person kayak", "imageID": "image_abc123", "additionalImageIDs": ["image_def456"], "pricePerHourCents": 0, "basePriceCents": 5000, "pricingTemplateID": "pricing_template_abc", "categoryID": "category_xyz", "companyID": "company_abc123", "updatedAt": 1711270800000, "archived": false, "sortOrder": 0 }
Field
Type
Required
Description
id
string
Yes
Product ID
name
string
Yes
Product name
description
string
Yes
Product description
imageID
string
Yes
Primary image ID
basePriceCents
number
Yes
Base price in cents
pricePerHourCents
number
Yes
Hourly rate in cents (often 0 when using pricing templates)
pricingTemplateID
string
No
Pricing template ID
categoryID
string
No
Category ID
companyID
string
Yes
Company ID
archived
boolean
Yes
Whether product is archived
updatedAt
number
Yes
Unix ms
sortOrder
number
No
Display sort order
Update product
POST /product/:id
Same fields as create — all optional except id.
Delete product
DELETE /product/:id
Body: { "id": "product_abc123" }
List categories
GET /category
Query param
Type
Default
Description
withProducts
boolean
false
Include non-archived products in each category
Get category
GET /category/:id
Create category
POST /category
Body:
{ "id": "category_01923abc-def4-7890-abcd-ef1234567890", "name": "Water Sports" }
Update / delete category
POST /category/:id — partial update
DELETE /category/:id — body: { "id": "category_abc123" }
List stock
GET /stock
Query param
Type
Default
Description
productID
string
—
Filter by product
locationID
string
—
Filter by location
withTracker
boolean
false
Include GPS tracker data
withLock
boolean
false
Include lock data
withCurrentReservation
boolean
false
Include active reservation
withReservations
boolean
false
Include reservation preview
reservationDateRange
object
—
{ "from": number, "to": number } for reservation overlap
stockIDSearch
string
—
Search by stock identifier
excludeStockID
string/array
—
Exclude stock row(s)
limit
number
—
Maximum results
Search stock
GET /stock/search?query=KAY-01
Search by human-readable stock identifier. Returns up to 5 matches with product, location, tracker, and current reservation.
Get stock
GET /stock/:id
Query param
Type
Default
Description
withCurrentReservationOnly
boolean
false
Only load the active hire reservation
Returns stock with product, location, tracker, lock, and reservation data.
Create stock
POST /stock
Body:
{ "id": "stock_01923abc-def4-7890-abcd-ef1234567890", "productID": "product_abc123", "locationID": "location_xyz", "stockID": "KAY-01", "lockID": "lock_abc", "trackerID": "tracker_xyz", "archived": false }
Field
Type
Required
Description
id
string
Yes
Stock row ID
productID
string
Yes
Product this unit belongs to
locationID
string
Yes
Location where stock is held
stockID
string
Yes
Human-readable identifier (shown to operators)
lockID
string
No
Associated lock ID
trackerID
string
No
Associated GPS tracker ID
archived
boolean
No
Defaults to false
Update / delete stock
POST /stock/:id — partial update
DELETE /stock/:id — body: { "id": "stock_abc123" }
List locations
GET /location
Query param
Type
Description
nameSearch
string
Filter by location name
excludeId
string
Exclude a location
limit
number
Maximum results
ids
array
Filter to specific location IDs
stockProductIDs
array
Only locations with stock for these products
Get location
GET /location/:id
Create location
POST /location
Body:
{ "id": "location_01923abc-def4-7890-abcd-ef1234567890", "name": "Main Depot", "address": "456 Industrial Ave", "lat": -33.8688, "lng": 151.2093, "accessDetails": "Gate code instructions", "taxRateOverride": null, "opens": 28800000, "closes": 61200000, "archived": false }
Field
Type
Required
Description
id
string
Yes
Location ID
name
string
Yes
Location name
address
string
No
Street address
lat, lng
number
No
Coordinates
accessDetails
string
No
Customer-facing access instructions
taxRateOverride
number
No
Override company tax rate
opens, closes
number
No
Operating hours as ms from midnight
archived
boolean
No
Defaults to false
Update location
POST /location/:id — partial update
List / search / get
GET /pricing-template — list shared pricing templates in the company
GET /pricing-template/search?query=Daily — search shared templates by name
GET /pricing-template/:id — get by ID
Query parameters (list / search):
Parameter
Type
Default
Description
limit
number
—
Maximum results (list only)
query
string
—
Name search text (search only)
include_product_scoped
boolean
false
Include product-owned templates. Defaults to shared templates only.
Create pricing template
POST /pricing-template
Body:
{ "id": "pricing_template_01923abc-def4-7890-abcd-ef1234567890", "name": "Daily Rate", "type": "tiered", "template": { "tiers": [ { "name": "1 Day", "price_multiplier": 1, "duration": 1, "duration_unit": "days" }, { "name": "3 Days", "price_multiplier": 2.5, "duration": 3, "duration_unit": "days" } ], "day_after": { "price_multiplier": 0.8 }, "example_base_price_cents": 20000 } }
Field
Type
Required
Description
id
string
Yes
Template ID
name
string
Yes
Template name
type
string
No
Defaults to "tiered". "product" is a legacy alias for tiered.
template.tiers
array
Yes
Pricing tiers with name, price_multiplier, duration, duration_unit (hours or days)
template.day_after
object
Yes
Additional day rate: { "price_multiplier": number }
template.example_base_price_cents
number
No
Default base price in cents applied when assigning this template to a product
Update / delete
POST /pricing-template/:id — partial update
DELETE /pricing-template/:id — body: { "id": "pricing_template_abc123" }
POST /pricing/calculate
Calculate the hire price for a cart of products at a location over a start/end window. Uses the same pricing path as checkout — pricing templates, time-based modifiers, location tax overrides, coupons, and add-ons.
Body:
{ "location_id": "location_abc123", "start_time": 1711270800000, "end_time": 1711357200000, "cart": [ { "product_id": "product_abc", "quantity": 2 }, { "product_id": "product_xyz", "quantity": 1 } ], "coupon_id": "coupon_summer20", "service_ids": ["service_delivery"] }
Field
Type
Required
Description
location_id
string
Yes
Location ID (affects tax via taxRateOverride)
start_time
number
Yes
Hire start time (Unix ms, UTC)
end_time
number
Yes
Hire end time (Unix ms, UTC). Must be after start_time
cart
array
Yes
Cart lines: { "product_id": string, "quantity": positive integer }
coupon_id
string
No
Optional coupon to apply to the total
service_ids
array
No
Optional add-on/service IDs to include
Response:
{ "currency": "AUD", "total_price_cents": 27500, "subtotal_cents": 25000, "tax_cents": 2500, "discount_cents": 0, "subtitle": "1 Day", "lines": [ { "product_id": "product_abc", "quantity": 2, "unit_period_price_cents": 10000, "line_subtotal_cents": 20000, "subtitle": "1 Day" }, { "product_id": "product_xyz", "quantity": 1, "unit_period_price_cents": 5000, "line_subtotal_cents": 5000, "subtitle": "1 Day" } ] }
Response field
Type
Description
currency
string
Company currency code
total_price_cents
number
Final amount to charge (includes tax)
subtotal_cents
number
Amount before tax (or tax-stripped when tax is inclusive)
tax_cents
number
Tax component in cents
discount_cents
number
Coupon discount applied in cents
subtitle
string
Human-readable tier/label from pricing
lines
array
Per-product unit and line totals for the hire window
List coupons
GET /coupon?archived=false
Query param
Type
Default
Description
archived
boolean
false
Include archived coupons when true
Search / get
GET /coupon/search?query=SUMMER — search active coupons by name
GET /coupon/:id — get by ID
Create coupon
POST /coupon
Body:
{ "id": "coupon_01923abc-def4-7890-abcd-ef1234567890", "name": "SUMMER20", "uses": 100, "used": 0, "staticDiscount": 0, "percentageDiscount": 20, "archived": false }
Field
Type
Required
Description
id
string
Yes
Coupon ID
name
string
Yes
Coupon code/name
uses
number
No
Maximum uses. Defaults to 0 (unlimited)
staticDiscount
number
No
Fixed discount in cents
percentageDiscount
number
No
Percentage discount (e.g. 20 = 20%)
archived
boolean
No
Defaults to false
Set either staticDiscount or percentageDiscount, not both.
Update / archive
POST /coupon/:id — partial update
POST /coupon/:id/archive — body: { "id": "coupon_abc123" }
List locks
GET /lock
Returns stock locks visible to the user, scoped by location access, with related stock.
Search locks
GET /lock/search?query=IGLOO-01
Search by lock identifier. Returns up to 5 matches.
List trackers
GET /tracker
Query param
Type
Description
limit
number
Maximum results
ids
array
Filter to specific tracker IDs
Search trackers
GET /tracker/search?query=Trailer&limit=5
Query param
Type
Default
Description
query
string
Yes
Search by name, type, or ID
limit
number
5
Maximum results
Get tracker
GET /tracker/:id
Update manual tracker (legacy)
PUT /tracker
Body:
{ "id": "tracker_001", "lat": "-33.8688", "lng": "151.2093", "battery": 85, "speed": "0", "name": "Trailer GPS" }
Read inbox
GET /inbox/notifications
Query param
Type
Default
Description
query.limit
number
20
Max notifications (1–100)
query.order_id
string
—
Filter by booking ID. When set, returns read and unread
query.stock_id
string
—
Filter by stock row ID or identifier
query.read_status
string
unread
unread, read, or all. Defaults to all when order_id or stock_id is set
Example:
GET /inbox/notifications?query={"limit":10,"read_status":"unread"}
Query reports
GET /reports/query
Query param
Type
Description
report
string
Required. booking_analytics, performance, customer_analytics, or demand
query.date_from
number
Report window start (Unix ms)
query.date_to
number
Report window end (Unix ms)
query.location_id
string
Location filter
query.product_id
string
Product filter
query.category_id
string
Category filter
query.limit
number
Max rows in ranked sections (1–50, default 10)
Example:
GET /reports/query?report=booking_analytics&query={"date_from":1711270800000,"date_to":1711357200000,"limit":10}
Response:
{ "report": "booking_analytics", "query": { "date_from": 1711270800000, "date_to": 1711357200000, "limit": 10 }, "generated_at": 1711270800000, "result": { } }
Work orders, parts, inspections, issue reports, and meters. Amounts are in cents. Dates are Unix milliseconds (UTC).
Stock IDs on these endpoints are the row id from
GET /stockorGET /stock/search(stock_…or a UUID). Do not pass the human-readable label, such asKAY-01.
nextDueis how much life is left until the next check, not a last-serviced date. A 10,000 km service with 7,000 km already done is{ "type": "meter_value", "meterKey": "distance_km", "remaining": 3000 }. Pass the full interval when the item is new or was just serviced.readingsis the current meter snapshot, for example{ "distance_km": 45000 }. Live GPS and stock readings are used when you omit it.
List work orders
GET /maintenance
Open work orders with stock, inspections, and lock access. All excludes work orders whose end date is already past.
Query param
Type
Default
Description
status
string
All
All, Ongoing, Upcoming, Unscheduled, or Past
limit
number
—
Maximum results
Response: Array of work orders. Each includes id, number, label, status (open or done), priority, note, startDate, endDate, blocksAvailability, assigneeUserID, stockID, stockLabel, productName, locationName, inspections, and access (stock and location lock codes for the downtime window).
List work order history
GET /maintenance/history
Past and current work orders, with stock, costs, and lock access.
Query param
Type
Description
limit
number
Maximum results
Get work order
GET /maintenance/:id
One work order, including stock, costs, inspections, and lock access.
Path parameter: id — work order ID
List work orders for a stock item
GET /stock/:stockID/maintenance
Query param
Type
Description
stockID
string
Stock row ID (path)
minEndDate
number
Only work orders ending after this Unix ms, or with no end date
Create work order
POST /maintenance
Creates an open work order on a stock item. If both startDate and endDate are set and blocksAvailability is omitted, the item is blocked from hire for that window.
Body:
{ "stockID": "stock_abc123", "note": "10,000 km service", "priority": "high", "assigneeUserID": "user_abc", "startDate": 1711270800000, "endDate": 1711357200000, "blocksAvailability": true, "photoImageIDs": ["image_abc"] }
Field
Type
Required
Description
stockID
string
Yes
Stock row ID
note
string
No
Title or notes. Defaults to General maintenance check
priority
string
No
urgent, high, medium, or low
assigneeUserID
string
No
Teammate user ID. null clears the assignee on update
startDate
number
No
Downtime start, Unix ms
endDate
number
No
Downtime end, Unix ms
blocksAvailability
boolean
No
Block the item from hire for the downtime window
photoImageIDs
array
No
Image IDs
id
string
No
Work order ID. Defaults to maintenance_<uuid>
Update work order
POST /maintenance/:id
Partial update of notes, schedule, priority, assignee, photos, or stock. Body includes id (must match the path) plus any fields from create.
Complete work order
POST /maintenance/:id/complete
Marks the work order done and records who completed it.
Body: { "id": "maintenance_abc123" }
Reopen work order
POST /maintenance/:id/reopen
Sets status back to open and clears the completion fields.
Body: { "id": "maintenance_abc123" }
Cancel work order
POST /maintenance/:id/cancel
Archives the work order.
Body: { "id": "maintenance_abc123" }
Add cost
POST /maintenance/:maintenanceID/cost
Adds a parts or labour cost. Amount is in cents.
Body:
{ "maintenanceID": "maintenance_abc123", "name": "Brake pads", "amountCents": 8500, "maintainedElementIDs": ["maintained_element_stock_abc_maintenance_schedule_xyz"], "orderID": "order_abc123" }
Field
Type
Required
Description
maintenanceID
string
Yes
Work order ID (must match the path)
name
string
Yes
Cost label
amountCents
number
Yes
Cost in cents
maintainedElementIDs
array
No
Stock part IDs this cost applies to
orderID
string
No
Related booking ID
id
string
No
Cost ID. Generated if omitted (mcost_…)
Update cost
POST /maintenance-cost/:id
Partial update. Set archived to true to remove a cost.
Field
Type
Required
Description
id
string
Yes
Cost ID
name
string
No
Cost label
amountCents
number
No
Cost in cents
maintainedElementIDs
array
No
Stock part IDs
orderID
string
No
Related booking ID. null clears it
archived
boolean
No
Archive the cost
A part definition (maintenance_schedule_…) is the reusable check, such as "oil" or "brakes". A stock part (maintained_element_<stockID>_<scheduleID>) is that part attached to one unit. GET /maintenance-part returns nextDueFields, which is the nextDue shape to send when the unit is already in use.
List parts
GET /maintenance-part
Query param
Type
Default
Description
includeArchived
boolean
false
Include archived part definitions
Get part
GET /maintenance-part/:id
Part definition and its due-date rules, including nextDueFields.
Get stock status
GET /stock/:id/status
Fleet status for one unit: overall down state, each part's status, due label, remaining life, and nextDue you can write back.
Response includes: id, stockLabel, productName, locationName, status (active, flagged, soft_down, or hard_down), statusLabel, openIssueCount, and parts.
List parts on a stock item
GET /stock/:stockID/parts
Parts on one unit, with status, due label, remaining life, open issues, and nextDue.
Response: { "stockID", "stockLabel", "maintenance" } where maintenance matches the status payload above.
Save part
POST /maintenance-part
Creates or updates a part definition and its due-date rules in one call. Pass attachStockID to attach it to a unit while saving. When that unit is already in use, pass nextDue. Saving re-runs due checks on every unit that has this part.
Body:
{ "name": "Oil service", "publiclyReportable": true, "triggers": [ { "type": "meter_value", "meterKey": "distance_km", "operator": "gte", "softDownAt": 10000, "hardDownAt": 12000 } ], "attachStockID": "stock_abc123", "nextDue": [ { "type": "meter_value", "meterKey": "distance_km", "remaining": 3000 } ], "readings": { "distance_km": 45000 } }
Field
Type
Required
Description
name
string
Yes
Part name
triggers
array
No
Due-date rules. Defaults to []
triggers[].type
string
Yes
calendar_days, bookings, booked_hours, meter_value, meter_stale, or at_will
triggers[].softDownAt
number
No
Check interval: days, bookings, booked hours, or meter units. Example: 10000 for every 10,000 km
triggers[].hardDownAt
number
No
Hard-down threshold, same unit as the rule
triggers[].meterKey
string
No
Required for meter_value and meter_stale. Example: distance_km
triggers[].operator
string
No
gte for incrementing meters such as odometer or hours. lte for falling levels such as battery. Defaults to gte for meter_value
triggers[].id
string
No
Trigger ID. Generated if omitted
id
string
No
Part ID. Defaults to maintenance_schedule_<uuid>
icon
string
No
Icon name. null clears it
publiclyReportable
boolean
No
Customers can report issues against this part
attachStockID
string
No
Attach the part to this stock row while saving
nextDue
array
No
Remaining until the next check. See the callout above
readings
object
No
Current meter readings to snapshot against
Attach part
POST /maintenance-part/:scheduleID/attach
Attaches an existing part to one or more stock items. Pass nextDue when a unit is already in use. readings applies only when stockIDs has a single item.
Body:
{ "scheduleID": "maintenance_schedule_abc", "stockIDs": ["stock_abc123"], "nextDue": [ { "type": "calendar_days", "remaining": 14 } ] }
Field
Type
Required
Description
scheduleID
string
Yes
Part ID (must match the path)
stockIDs
array
Yes
One or more stock row IDs
nextDue
array
No
Remaining until the next check for each interval rule
readings
object
No
Current readings when attaching a single item
Response: { "scheduleID", "attached", "parts" }
Set next due
POST /stock-part/:id/next-due
Sets remaining life on a stock part. id is the stock part ID from GET /stock/:stockID/parts. Use the same nextDue shape that list returns.
Body:
{ "id": "maintained_element_stock_abc_maintenance_schedule_xyz", "nextDue": [ { "type": "bookings", "remaining": 10 } ], "readings": { "distance_km": 45000 } }
nextDue is required and must contain at least one entry. type is booked_hours, bookings, calendar_days, or meter_value. meterKey is required when type is meter_value.
Detach part
POST /stock-part/:id/detach
Removes a part from a stock item.
Body: { "id": "maintained_element_…" }
Response: { "id", "success": true }
List inspections
GET /maintenance/:maintenanceID/inspections
Inspections recorded on a work order, oldest first.
Mark inspected
POST /maintenance-check
Marks a stock part inspected, or records a custom inspection on a work order. Resets that part's due usage. Provide maintainedElementID or title.
Body:
{ "maintainedElementID": "maintained_element_…", "maintenanceID": "maintenance_abc123", "note": "Oil and filter replaced", "photoImageIDs": ["image_abc"], "title": "Pre-hire check" }
Field
Type
Required
Description
maintainedElementID
string
No
Stock part ID. Required unless title is set
title
string
No
Custom inspection title when there is no part
maintenanceID
string
No
Work order to attach the inspection to
note
string
No
Inspection note
photoImageIDs
array
No
Image IDs
Response: Inspection row. ID is generated (mcheck_…).
Update inspection
POST /maintenance-check/:id
Updates note, photoImageIDs, or title. Body includes id.
Delete inspection
DELETE /maintenance-check/:id
Removes the inspection and restores the previous last-checked time.
Body: { "id": "mcheck_…" }
Response: { "id", "success": true }
Reset check period
POST /stock-part/:id/reset-check-period
Resets a part's usage clock without recording a full inspection.
Body:
{ "id": "maintained_element_…", "maintenanceID": "maintenance_abc123", "partName": "Oil service" }
maintenanceID and partName are optional.
List issue reports
GET /issue-report
Defaults to unresolved reports.
Query param
Type
Default
Description
includeResolved
boolean
false
Include resolved reports
stockID
string
—
Filter to one stock row
limit
number
—
Maximum results
Get issue report
GET /issue-report/:id
Issue report with stock, booking, and linked parts.
Report issue
POST /issue-report
Files a staff issue against a stock item. Optionally link it to a part. Can mark the unit soft down or hard down.
Body:
{ "stockID": "stock_abc123", "description": "Rear brake is spongy", "status": "soft_down", "maintainedElementID": "maintained_element_…", "orderID": "order_abc123", "photoImageIDs": ["image_abc"], "title": "Spongy rear brake" }
Field
Type
Required
Description
stockID
string
Yes
Stock row ID
description
string
Yes
What is wrong
status
string
No
unknown (default), soft_down, or hard_down
maintainedElementID
string
No
Stock part ID. Omit for an item-level issue
orderID
string
No
Related booking ID
photoImageIDs
array
No
Image IDs
title
string
No
Defaults from the part name and description
Response: Issue report. ID is issue_report_<uuid>.
Resolve issue
POST /issue-report/:id/resolve
Marks the report resolved. This does not reset part usage — use POST /maintenance-check for that.
Body: { "id": "issue_report_…" }
Meters store readings such as odometer or engine hours. Recording readings refreshes part due status.
List meters
GET /meter
Query param
Type
Default
Description
stockID
string
—
Only meters on this stock row
includeArchived
boolean
false
Include archived meters
Get meter
GET /meter/:id
Meter, including related stock.
Create meter
POST /meter
Body:
{ "name": "Odometer", "stockID": "stock_abc123", "source": "api", "externalID": "odometer-1", "readings": { "distance_km": 45000 } }
Field
Type
Required
Description
name
string
Yes
Meter name
stockID
string
No
Stock row to assign. Omit to create an unassigned meter
source
string
No
api (default), lockii_lock, lockii_gps, or manual
externalID
string
No
Your identifier for this meter
readings
object
No
Initial readings. Keys are meter keys such as distance_km
Response: Meter row. ID is meter_<uuid>.
Assign meter
POST /meter/:id/assign
Assigns a meter to a stock item, or unassigns it.
Body: { "id": "meter_abc", "stockID": "stock_abc123" }
stockID is required. Pass null to unassign.
Record meter readings
POST /meter/:id/readings
Merges readings onto a meter and refreshes part due status. Existing keys not in the body are left as they are.
Body: { "id": "meter_abc", "readings": { "distance_km": 46200 } }
Record stock readings
POST /stock/:stockID/readings
Merges readings onto a stock item and refreshes part due status.
Body: { "stockID": "stock_abc123", "readings": { "distance_km": 46200 } }
Response: { "readings" }
All requests are scoped to the company associated with your API key.
Location-scoped users only see data for locations they have access to.
Write operations require appropriate role permissions (e.g. payment refunds require organization:update).
Lockii User MCP — same capabilities as MCP tools for AI clients
Customer MCP — limited MCP for customer-facing support tools
Browse API — public endpoints for custom booking frontends
Connecting Zapier — no-code automations