Lockii
Lockii
Docs
  • Docs
  • Changelog
  • Feature requests
  • Support portal
    • Building a Marketplace App
    • User MCP
    • Login with Lockii
    • Building a Lockii App
    • Customer MCP
    • Lockii REST API
    • Booking API

Building a Marketplace App

Connect your marketplace or OTA to Lockii so operators can publish inventory and you can check availability and create bookings.

Use a marketplace app when your platform lists and sells rental inventory on behalf of Lockii operators. Operators connect your marketplace, choose which products to publish, and you push paid bookings into Lockii after you collect payment from the renter.

If you are building an accounting sync, automation tool, or other integration that is not a sales channel, see Building a Lockii App instead.


Get listed

Marketplace apps are reviewed before launch. Email [email protected] to finish your app review, you can start developing today without needing to contact us.

Include:

  • Your company and marketplace name

  • A short description of the integration

  • Your logo (square, PNG or SVG)

  • One or more HTTPS OAuth redirect URIs

  • Your connect URL (the page on your platform where an operator starts the connection)

  • Your webhook HTTPS endpoint

Once approved, Lockii registers your app and issues:

  • A client_id and client_secret

  • A webhook signing secret

Treat the client_secret like a password. Store it in a secrets manager — never in client-side code or version control. Rotation is available on request.


How it works

Connect operator → Discover listings → Check availability → Take payment → Create booking

Concept

Meaning

Connection

One Lockii operator who granted your marketplace access. Each connection has its own tokens.

Listing

A product the operator published to your marketplace, plus location and a display price.

Booking

A rental order in Lockii attributed to your marketplace.

Important behaviours:

  • Availability is not a stock number. It depends on start/end time, location, existing reservations, and buffer times. Always re-check near booking — never cache it as a static quantity.

  • No holds. The availability endpoint is informational. The binding check happens when you create the booking.

  • Auto-confirm with pending fallback. If capacity is free, the booking is confirmed. If not (for example another booking landed in between), it is created as pending_approval and the operator decides. Handle both outcomes.


Base URLs

Purpose

URL

API

https://dash.lockii.app/api/v1

OAuth

https://dash.lockii.app/api/oauth


Scopes

Request only what you need:

Scope

Grants

channel:read

Read published listings, check availability, read bookings you created

channel:write

Create and cancel bookings


OAuth connection flow

Lockii uses the OAuth 2.0 authorization code grant with refresh tokens. Each successful grant creates a connection for one operator. PKCE (S256) is supported and recommended.

1. Authorization request

While the operator is logged in on your platform, redirect them to:

https://dash.lockii.app/api/oauth/authorize
  ?client_id={your client_id}
  &redirect_uri={one of your registered redirect URIs}
  &response_type=code
  &scope=channel:read channel:write
  &state={opaque anti-CSRF value}
  &external_account_id={your seller account ID}
  &external_account_name={display name, optional}

external_account_id is required for marketplace apps. It is your identifier for the seller account starting the connection. Lockii stores it on the connection and echoes it in the API and webhooks.

Operators can also start from Settings → Integrations in Lockii if you provided a connect URL.

2. Consent

The operator signs in to Lockii, picks a company, and approves the scopes.

  • Approved → redirect to your redirect_uri with ?code=...&state=... (code expires in 10 minutes, single-use)

  • Declined → ?error=access_denied&state=...

Always verify state before continuing.

3. Token exchange

POST /api/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code={code}
&client_id={client_id}
&client_secret={client_secret}
&redirect_uri={same redirect_uri as authorize}

Response includes access_token, refresh_token, expires_in, scope, and connection_id. Store the token pair against your seller account, keyed by connection_id.

4. Refresh tokens

  • Access tokens last 60 minutes

  • Refresh tokens last 90 days and rotate on every use — always persist the new refresh token atomically

  • Reusing an already-rotated refresh token revokes the connection's tokens (replay protection)

POST /api/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token={current refresh token}
&client_id={client_id}
&client_secret={client_secret}

Refresh a few minutes before expiry, or on a 401 with error.code: "token_expired".

5. Pause, disconnect, reconnect

  • Operators can pause or disconnect from Lockii at any time

  • Paused connections return 403 with connection_paused

  • Disconnect revokes tokens and sends connection.disconnected — stop showing their listings immediately

  • Running authorize again for the same operator/seller pair reuses the existing connection_id and publications, with fresh tokens

  • You can revoke with POST /api/oauth/revoke (RFC 7009)


Calling the Channel API

Every request uses the connection's access token:

Authorization: Bearer lk_at_xxxxxxxxxxxxxxxx

The token identifies the connection — you never pass a company ID.

Conventions

  • Timestamps: ISO 8601 with offset, e.g. 2026-08-14T09:00:00+10:00. Display times in the listing location's IANA timezone.

  • Money: integer minor units (cents) plus ISO currency, e.g. { "amount": 36000, "currency": "AUD" }.

  • Pagination: cursor-based via next_cursor / ?cursor=.

  • Idempotency: booking creation is idempotent on your external_order.id. Always retry failed creates with the same ID.

Endpoints

Method

Path

Scope

Purpose

GET

/channel/connection

channel:read

Introspect the current connection

GET

/channel/listings

channel:read

List published listings

GET

/channel/listings/{id}

channel:read

Single listing

POST

/channel/availability

channel:read

Check availability for a time window

POST

/channel/bookings

channel:write

Create a booking (after payment)

GET

/channel/bookings/{id}

channel:read

Get booking state

POST

/channel/bookings/{id}/cancel

channel:write

Cancel a booking

Availability

{
  "listing_ids": ["listing_123"],
  "start_at": "2026-08-14T09:00:00+10:00",
  "end_at": "2026-08-17T09:00:00+10:00",
  "quantity": 1
}

Call this when a renter picks dates. Do not bulk-poll it to build a calendar cache.

Create a booking

Call after you have collected payment:

{
  "external_order": {
    "id": "mp_order_89201",
    "number": "MP-89201",
    "url": "https://marketplace.example/orders/89201"
  },
  "lines": [{ "listing_id": "listing_123", "quantity": 1 }],
  "start_at": "2026-08-14T09:00:00+10:00",
  "end_at": "2026-08-17T09:00:00+10:00",
  "customer": {
    "first_name": "Jane",
    "last_name": "Smith",
    "email": "[email protected]",
    "phone": "+61400000000"
  },
  "payment": {
    "status": "paid",
    "amount": 41580,
    "currency": "AUD",
    "external_payment_id": "pay_7832"
  },
  "notes": "Optional notes for the operator."
}

Example response:

{
  "id": "booking_01K4A2...",
  "number": "L-10492",
  "status": "confirmed",
  "external_order_id": "mp_order_89201",
  "confirmation_url": "https://book.lockii.app/{company}/confirmation/private_...",
  "start_at": "2026-08-14T09:00:00+10:00",
  "end_at": "2026-08-17T09:00:00+10:00"
}

Both confirmed and pending_approval responses are HTTP 201. Treat status as the source of truth. For pending_approval, tell the renter their booking is awaiting confirmation and be ready to refund if it is declined.

Optional — send renters to the Lockii confirmation page. The response includes confirmation_url. You can link to it from your post-purchase screen or confirmation email so the customer can open pickup instructions, access codes, and booking details on the operator's Lockii page. This is optional — keep your own confirmation flow if you prefer, and offer the Lockii link as an extra option when it helps the renter complete pickup.

The same confirmation_url is returned on get and cancel responses. Booking date changes are not supported in v1 — cancel and re-book, or send the renter to the operator.


What operators do in Lockii

  1. Connect your marketplace from Settings → Integrations (or from your connect URL).

  2. On each product, use the Channels sidebar to publish that product to your marketplace.

  3. Unpublished products are invisible to you.

  4. Operators can pause or disconnect the connection at any time.

A product available at multiple locations appears as one listing per location.


Webhooks

Lockii POSTs JSON events to your registered webhook URL. Events cover all your connections and include connection_id.

Event

When

connection.activated

Operator completed OAuth (or reconnected)

connection.disconnected

Operator disconnected — remove their listings

listing.published

Product published to your marketplace

listing.updated

Published product details changed

listing.unpublished

Product unpublished — remove it

booking.confirmed

Booking confirmed (including after operator approval)

booking.cancelled

Booking cancelled or declined

Payloads are thin (ids + timestamps). Re-fetch the resource via the API. Respond with 2xx within 10 seconds. Delivery order is not guaranteed; deduplicate on event id.

Signature verification

Each delivery includes:

Lockii-Event-Id: evt_...
Lockii-Event-Type: listing.updated
Lockii-Signature: t={unix},v1={hmac_hex}

The signature is HMAC-SHA256 of {t}.{raw_request_body} using your webhook signing secret. Reject deliveries older than 5 minutes. Compute the HMAC over the raw body bytes before JSON parsing.


Recommended flow

Connect

  1. Operator clicks Connect Lockii (or arrives from the Lockii directory).

  2. Complete OAuth; store tokens by connection_id.

  3. Page through GET /channel/listings and import the catalog.

Ongoing

  1. Apply listing.* webhooks by re-fetching the listing.

  2. Re-sync the full listing set periodically (e.g. daily).

  3. Refresh access tokens proactively; persist rotated refresh tokens atomically.

Checkout

  1. POST /channel/availability when the renter selects dates.

  2. Collect payment on your side.

  3. POST /channel/bookings with your external order ID.

  4. Optionally give the renter confirmation_url (button or email link) so they can open the Lockii confirmation page for pickup and access details.

  5. If confirmed — done. If pending_approval — wait for booking.confirmed or booking.cancelled; refund on decline.


Go-live checklist

  • Listed after approval from [email protected]

  • client_secret and tokens stored securely; tokens keyed by connection_id

  • OAuth state verified; PKCE implemented

  • external_account_id sent on every authorize request

  • Token refresh handles rotation atomically

  • Webhook endpoint live with signature verification and event deduplication

  • Full listing sync + webhooks + periodic reconciliation

  • Availability checked at date selection, not cached as static stock

  • Booking retries reuse the same external_order.id

  • Optionally surface confirmation_url to renters after booking

  • pending_approval handled in renter UX

  • connection.disconnected and listing.unpublished remove content promptly

  • Times displayed in the listing location's timezone


Related

  • Building a Lockii App — non-marketplace apps (accounting, automation, etc.)

  • Lockii REST API — full standard API reference

  • Login with Lockii — user-delegated OAuth (different from App Platform apps)

PrevCustomer Accounts
NextUser MCP
Was this helpful?