https://dash.lockii.app/api/v1Create 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 |
|
Bearer token |
|
Query string |
|
Lockii uses prefixed IDs. Generate new IDs with a UUID v7 suffix:
Resource | Format | Example |
|---|---|---|
Booking |
|
|
Customer |
|
|
ect |
|
|
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}GET /booking
Returns a filtered list of bookings with customer, location, company, and order line details.
Query parameters:
Parameter | Type | Default | Description |
|---|---|---|---|
| number |
| Maximum results to return |
| string |
|
|
| string |
| Sort field: |
| object | — | Hire window overlap filter: |
| object | — | Created-at filter: |
| object | — | Price filter in whole dollars: |
| string | — | Filter to bookings containing this product |
| string | — | Filter to bookings containing this stock row |
| string | — | Filter to bookings with products in this category |
| string | — | Filter to bookings at this location |
| number | — | Bookings ending on or after this Unix ms timestamp |
| array | — |
|
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/: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_abc123POST /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 |
|---|---|---|---|
| string | Yes | Internal booking ID |
| object | Yes | Requested changes — only include fields you want to change |
| number | No | New start time (Unix ms) |
| number | No | New end time (Unix ms) |
| string | No | New pickup/return location |
| array | No | Replacement line items: |
| string | No | Set to |
| string | No |
|
| number | No | Refund percentage for cancellations (0–100). Defaults to |
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 |
|---|---|---|---|
| string | Yes | Booking ID (must match path |
| string | Yes | Reason for manual pickup |
Response:
{ "success": true, "id": "order_abc123" }
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" }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 |
|---|---|---|---|
| string | Yes | Payment ID |
| number | Yes | Refund amount in cents (must be positive) |
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 |
|---|---|---|---|
| string | Yes | Booking to request payment for |
| number | Yes | Amount to request in cents |
| string | No | Payment ID. Defaults to a generated |
| string | No | Defaults to authenticated company |
Response: Payment row including paymentData.payment_link_url.
GET /customer
Query param | Type | Default | Description |
|---|---|---|---|
| string |
|
|
| number |
| Maximum results |
GET /customer/search?query=john
Query param | Type | Required | Description |
|---|---|---|---|
| string | Yes | Search by name, last name, email, or phone |
Returns up to 5 matches.
GET /customer/:id
Returns a single customer record.
GET /customer/:id/page
Returns customer profile with related non-pending bookings (including location, stock, order lines).
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 |
|---|---|---|---|
| string | Yes | Customer ID ( |
| string | No | First name. Defaults to |
| string | No | Last name. Defaults to |
| string | No | Email address |
| string | No | Phone number |
| string | No | Country/area code |
| string | No | Address fields |
| string | No | Defaults to authenticated company |
| string | No | Stripe customer ID if linked |
POST /customer/:id
Same fields as create — all optional except id. Only include fields you want to change.
DELETE /customer/:id
Body:
{ "id": "customer_abc123" }
POST /customer/:id/block
Body:
{
"id": "customer_abc123",
"reason": "Repeated no-shows"
}
POST /customer/:id/unblock
Body:
{ "id": "customer_abc123" }
POST /customer/:id/manual-verify
Body:
{
"id": "customer_abc123",
"identityLink": "https://...",
"identityExpiresAt": 1742800800000
}
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Customer ID |
| string | No | Supporting verification link |
| number | No | Expiry Unix ms. Defaults to one year from now |
POST /customer/:id/verification-link
Body:
{
"customer_id": "customer_abc123",
"send_email": true
}
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Customer ID |
| boolean | No | Email the link to the customer. Defaults to |
GET /product
Query param | Type | Default | Description |
|---|---|---|---|
| string | — | Filter by category |
| string | — | Filter by product name (partial match) |
| string | — | Exclude a product ID |
| number | — | Maximum results |
| boolean |
| Include non-archived stock rows |
GET /product/:id
Query param | Type | Default | Description |
|---|---|---|---|
| boolean |
| Exclude archived products |
Returns product with category, pricingTemplate, and optionally stock.
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 |
|---|---|---|---|
| string | Yes | Product ID |
| string | Yes | Product name |
| string | Yes | Product description |
| string | Yes | Primary image ID |
| number | Yes | Base price in cents |
| number | Yes | Hourly rate in cents (often |
| string | No | Pricing template ID |
| string | No | Category ID |
| string | Yes | Company ID |
| boolean | Yes | Whether product is archived |
| number | Yes | Unix ms |
| number | No | Display sort order |
POST /product/:id
Same fields as create — all optional except id.
DELETE /product/:id
Body: { "id": "product_abc123" }
GET /category
Query param | Type | Default | Description |
|---|---|---|---|
| boolean |
| Include non-archived products in each category |
GET /category/:id
POST /category
Body:
{
"id": "category_01923abc-def4-7890-abcd-ef1234567890",
"name": "Water Sports"
}
POST /category/:id — partial updateDELETE /category/:id — body: { "id": "category_abc123" }
GET /stock
Query param | Type | Default | Description |
|---|---|---|---|
| string | — | Filter by product |
| string | — | Filter by location |
| boolean |
| Include GPS tracker data |
| boolean |
| Include lock data |
| boolean |
| Include active reservation |
| boolean |
| Include reservation preview |
| object | — |
|
| string | — | Search by stock identifier |
| string/array | — | Exclude stock row(s) |
| number | — | Maximum results |
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/:id
Query param | Type | Default | Description |
|---|---|---|---|
| boolean |
| Only load the active hire reservation |
Returns stock with product, location, tracker, lock, and reservation data.
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 |
|---|---|---|---|
| string | Yes | Stock row ID |
| string | Yes | Product this unit belongs to |
| string | Yes | Location where stock is held |
| string | Yes | Human-readable identifier (shown to operators) |
| string | No | Associated lock ID |
| string | No | Associated GPS tracker ID |
| boolean | No | Defaults to |
POST /stock/:id — partial updateDELETE /stock/:id — body: { "id": "stock_abc123" }
GET /location
Query param | Type | Description |
|---|---|---|
| string | Filter by location name |
| string | Exclude a location |
| number | Maximum results |
| array | Filter to specific location IDs |
| array | Only locations with stock for these products |
GET /location/:id
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 |
|---|---|---|---|
| string | Yes | Location ID |
| string | Yes | Location name |
| string | No | Street address |
| number | No | Coordinates |
| string | No | Customer-facing access instructions |
| number | No | Override company tax rate |
| number | No | Operating hours as ms from midnight |
| boolean | No | Defaults to |
POST /location/:id — partial update
GET /pricing-template — list all templates
GET /pricing-template/search?query=Daily — search by name
GET /pricing-template/:id — get by ID
POST /pricing-template
Body:
{
"id": "pricing_template_01923abc-def4-7890-abcd-ef1234567890",
"name": "Daily Rate",
"type": "time",
"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
}
}
}
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Template ID |
| string | Yes | Template name |
| string | No | Defaults to |
| array | Yes | Pricing tiers with |
| object | Yes | Additional day rate: |
POST /pricing-template/:id — partial updateDELETE /pricing-template/:id — body: { "id": "pricing_template_abc123" }
GET /coupon?archived=false
Query param | Type | Default | Description |
|---|---|---|---|
| boolean |
| Include archived coupons when |
GET /coupon/search?query=SUMMER — search active coupons by name
GET /coupon/:id — get by ID
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 |
|---|---|---|---|
| string | Yes | Coupon ID |
| string | Yes | Coupon code/name |
| number | No | Maximum uses. Defaults to |
| number | No | Fixed discount in cents |
| number | No | Percentage discount (e.g. |
| boolean | No | Defaults to |
Set either staticDiscount or percentageDiscount, not both.
POST /coupon/:id — partial updatePOST /coupon/:id/archive — body: { "id": "coupon_abc123" }
GET /lock
Returns stock locks visible to the user, scoped by location access, with related stock.
GET /lock/search?query=IGLOO-01
Search by lock identifier. Returns up to 5 matches.
GET /tracker
Query param | Type | Description |
|---|---|---|
| number | Maximum results |
| array | Filter to specific tracker IDs |
GET /tracker/search?query=Trailer&limit=5
Query param | Type | Default | Description |
|---|---|---|---|
| string | Yes | Search by name, type, or ID |
| number |
| Maximum results |
GET /tracker/:id
PUT /tracker
Body:
{
"id": "tracker_001",
"lat": "-33.8688",
"lng": "151.2093",
"battery": 85,
"speed": "0",
"name": "Trailer GPS"
}
GET /inbox/notifications
Query param | Type | Default | Description |
|---|---|---|---|
| number |
| Max notifications (1–100) |
| string | — | Filter by booking ID. When set, returns read and unread |
| string | — | Filter by stock row ID or identifier |
| string |
|
|
Example:
GET /inbox/notifications?query={"limit":10,"read_status":"unread"}
GET /reports/query
Query param | Type | Description |
|---|---|---|
| string | Required. |
| number | Report window start (Unix ms) |
| number | Report window end (Unix ms) |
| string | Location filter |
| string | Product filter |
| string | Category filter |
| number | Max rows in ranked sections (1–50, default |
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