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-...
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 updateDELETE /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 updateDELETE /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 updateDELETE /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 updatePOST /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": { } }
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