Skip to main content

Laabam One Public API (1.0.0)

Download OpenAPI specification:Download

The Laabam One API lets your systems and approved third parties read and write data in your company's Laabam One account — invoices, customers, products, payments — and send messages over SMS, WhatsApp and email.

Every request authenticates with two headers — X-Client-Id and X-Client-Secret, created in Settings → API Keys. See the Authentication and Security guides for the full details. Each operation below is marked x-status: available (callable today) or x-status: planned (contract defined, not yet built).

Invoices

✅ Read, create, send & void available (create posts the Sales JE + moves stock; INR). Update (PATCH draft) planned.

List invoices

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 25

Page size (1–100).

cursor
string

Opaque cursor from the previous response's paging.next_cursor.

status
string
Enum: "unpaid" "partial" "paid"

Filters on the invoice's payment_status (not the status field also returned in the response — they are different columns). Voided invoices are removed, so they can never appear in this list.

customer_id
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "paging": {
    }
}

Create an invoice

Creates an invoice, posts the Sales journal entry (DR receivable, CR sales + GST split) and deducts stock — the exact same accounting engine as the in-app flow. Totals, tax and round-off are computed server-side and are authoritative (client-sent totals are ignored). Each line requires item_name, quantity, unit, unit_price and tax_rate. INR only in v1 (recurring, attachments and pay-at-create are app-only).

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

header Parameters
Idempotency-Key
string <uuid>

A unique UUID so retries don't double‑create/charge/send. Cached 24h.

Request Body schema: application/json
required
customer_id
required
string
invoice_date
required
string <date>
due_date
string <date>
required
Array of objects (InvoiceItemCreate) non-empty
document_type
string
Default: "invoice"
Enum: "invoice" "quotation" "estimate" "proforma_invoice" "sales_order"
invoice_number
string <= 50 characters

Auto-generated when omitted.

reference_number
string <= 255 characters
gst_invoice_type
string
Enum: "regular" "bill_of_supply" "export_sez"
reverse_charge
string
Enum: "Y" "N"
terms
string
notes
string

Responses

Request samples

Content type
application/json
{
  • "customer_id": "string",
  • "invoice_date": "2019-08-24",
  • "due_date": "2019-08-24",
  • "items": [
    ],
  • "document_type": "invoice",
  • "invoice_number": "string",
  • "reference_number": "string",
  • "gst_invoice_type": "regular",
  • "reverse_charge": "Y",
  • "terms": "string",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get an invoice

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a draft invoice

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
required
customer_id
required
string
invoice_date
required
string <date>
due_date
string <date>
required
Array of objects (InvoiceItemCreate) non-empty
document_type
string
Default: "invoice"
Enum: "invoice" "quotation" "estimate" "proforma_invoice" "sales_order"
invoice_number
string <= 50 characters

Auto-generated when omitted.

reference_number
string <= 255 characters
gst_invoice_type
string
Enum: "regular" "bill_of_supply" "export_sez"
reverse_charge
string
Enum: "Y" "N"
terms
string
notes
string

Responses

Request samples

Content type
application/json
{
  • "customer_id": "string",
  • "invoice_date": "2019-08-24",
  • "due_date": "2019-08-24",
  • "items": [
    ],
  • "document_type": "invoice",
  • "invoice_number": "string",
  • "reference_number": "string",
  • "gst_invoice_type": "regular",
  • "reverse_charge": "Y",
  • "terms": "string",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Void an invoice

Voids (soft-deletes) the invoice and reverses all its side-effects — its journal entries, any payments + their JEs, and restores deducted stock — the same reversal as the app. Returns a summary of what was reversed.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Email the invoice to the customer

Renders the invoice PDF (using your configured print template) and queues it for email to the customer — the same render the in‑app "Send" button uses. Recipients default to the invoice customer's email; override with email or emails[] (max 10). A draft invoice is marked as sent. Only channel: email is available today; WhatsApp invoice delivery is planned.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
optional
channel
string
Default: "email"
Value: "email"
email
string <email>

Single recipient (overrides the customer email).

emails
Array of strings <email> [ items <email > ]

Multiple recipients (max 10).

message
string <= 1000 characters

Optional note included in the email.

Responses

Request samples

Content type
application/json
{
  • "channel": "email",
  • "email": "user@example.com",
  • "emails": [
    ],
  • "message": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Customers

✅ Read, create, update & delete available (create also opens the Sundry Debtors ledger account).

List / search customers

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 25

Page size (1–100).

cursor
string

Opaque cursor from the previous response's paging.next_cursor.

q
string

Free‑text search (name / email / phone).

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "paging": {
    }
}

Create a customer

Creates a customer and its Sundry Debtors ledger account (same path as the UI). name, state and pincode are required. opening_balance and profile images are NOT settable via the API (the opening-balance ledger entry remains a UI-only action).

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

header Parameters
Idempotency-Key
string <uuid>

A unique UUID so retries don't double‑create/charge/send. Cached 24h.

Request Body schema: application/json
required
name
required
string <= 255 characters
email
string <email> <= 255 characters
phone
string <= 20 characters
phone_country_code
string
alternate_phone
string <= 20 characters
address
string
address_label
string
area
string
city
string
state
required
string
pincode
required
string
country
string <= 2 characters

ISO alpha-2.

gst_number
string <= 15 characters
gst_type
string
legal_name
string
pan_number
string <= 10 characters
customer_type
string
Enum: "individual" "business"
currency_code
string = 3 characters
discount
number [ 0 .. 100 ]
credit_limit
number >= 0
website_url
string <uri>
also_vendor
boolean
is_active
boolean
notes
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "phone_country_code": "string",
  • "alternate_phone": "string",
  • "address": "string",
  • "address_label": "string",
  • "area": "string",
  • "city": "string",
  • "state": "string",
  • "pincode": "string",
  • "country": "st",
  • "gst_number": "string",
  • "gst_type": "string",
  • "legal_name": "string",
  • "pan_number": "string",
  • "customer_type": "individual",
  • "currency_code": "str",
  • "discount": 100,
  • "credit_limit": 0,
  • "website_url": "http://example.com",
  • "also_vendor": true,
  • "is_active": true,
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a customer

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a customer

Partial update — send only the fields you want to change. Renaming keeps the linked ledger account names in sync.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
optional
name
required
string <= 255 characters
email
string <email> <= 255 characters
phone
string <= 20 characters
phone_country_code
string
alternate_phone
string <= 20 characters
address
string
address_label
string
area
string
city
string
state
required
string
pincode
required
string
country
string <= 2 characters

ISO alpha-2.

gst_number
string <= 15 characters
gst_type
string
legal_name
string
pan_number
string <= 10 characters
customer_type
string
Enum: "individual" "business"
currency_code
string = 3 characters
discount
number [ 0 .. 100 ]
credit_limit
number >= 0
website_url
string <uri>
also_vendor
boolean
is_active
boolean
notes
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "phone_country_code": "string",
  • "alternate_phone": "string",
  • "address": "string",
  • "address_label": "string",
  • "area": "string",
  • "city": "string",
  • "state": "string",
  • "pincode": "string",
  • "country": "st",
  • "gst_number": "string",
  • "gst_type": "string",
  • "legal_name": "string",
  • "pan_number": "string",
  • "customer_type": "individual",
  • "currency_code": "str",
  • "discount": 100,
  • "credit_limit": 0,
  • "website_url": "http://example.com",
  • "also_vendor": true,
  • "is_active": true,
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Soft‑delete a customer

Soft-deletes the customer and removes its debtor account. Blocked with 409 if the customer has invoices, payments or posted ledger transactions. If the record is also a vendor, only the customer role is removed (vendor data is retained).

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Products

✅ Read, create, update & stock-adjust available.

List / search products

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 25

Page size (1–100).

cursor
string

Opaque cursor from the previous response's paging.next_cursor.

q
string
category_id
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "paging": {
    }
}

Create a product

Creates a product. If track_stock is true and opening_stock > 0, an opening stock movement (and a batch when is_batch_tracked) is recorded. name and unit_id are required. Images, variants and bundles are not settable via the API.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
name
required
string
unit_id
required
integer

Required. Must exist in the company's units.

type
string
Default: "product"
Enum: "product" "service"
invoice_name
string

Defaults to name.

sku
string <= 100 characters

Must be unique.

barcode
string <= 100 characters

Must be unique.

category_id
integer
brand_id
integer
description
string
purchase_price
number >= 0
selling_price
number >= 0
mrp_price
number >= 0
selling_price_tax_mode
string
Enum: "exclusive" "inclusive"
gst_rate
number [ 0 .. 100 ]
hsn_code
string <= 20 characters
sac_code
string <= 20 characters
status
string
Default: "active"
Enum: "active" "inactive"
track_stock
boolean

Create only — not updatable via PATCH.

opening_stock
number
min_stock
number
max_stock
number
low_stock_alert
boolean
is_batch_tracked
boolean
is_expiry_tracked
boolean

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "unit_id": 0,
  • "type": "product",
  • "invoice_name": "string",
  • "sku": "string",
  • "barcode": "string",
  • "category_id": 0,
  • "brand_id": 0,
  • "description": "string",
  • "purchase_price": 0,
  • "selling_price": 0,
  • "mrp_price": 0,
  • "selling_price_tax_mode": "exclusive",
  • "gst_rate": 18,
  • "hsn_code": "string",
  • "sac_code": "string",
  • "status": "active",
  • "track_stock": true,
  • "opening_stock": 0,
  • "min_stock": 0,
  • "max_stock": 0,
  • "low_stock_alert": true,
  • "is_batch_tracked": true,
  • "is_expiry_tracked": true
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a product (with current stock)

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a product

Partial update of scalar fields (name, prices, tax/HSN, sku, status, …). Stock and track_stock are NOT updatable here — use the stock-adjustments endpoint to move stock.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
optional
name
string
unit_id
integer
invoice_name
string
sku
string <= 100 characters
barcode
string <= 100 characters
category_id
integer
brand_id
integer
description
string
purchase_price
number >= 0
selling_price
number >= 0
mrp_price
number >= 0
selling_price_tax_mode
string
Enum: "exclusive" "inclusive"
gst_rate
number [ 0 .. 100 ]
hsn_code
string <= 20 characters
sac_code
string <= 20 characters
status
string
Enum: "active" "inactive"
min_stock
number
max_stock
number
low_stock_alert
boolean

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "unit_id": 0,
  • "invoice_name": "string",
  • "sku": "string",
  • "barcode": "string",
  • "category_id": 0,
  • "brand_id": 0,
  • "description": "string",
  • "purchase_price": 0,
  • "selling_price": 0,
  • "mrp_price": 0,
  • "selling_price_tax_mode": "exclusive",
  • "gst_rate": 100,
  • "hsn_code": "string",
  • "sac_code": "string",
  • "status": "active",
  • "min_stock": 0,
  • "max_stock": 0,
  • "low_stock_alert": true
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Adjust stock

Records a manual stock-adjustment movement and moves the product's current stock.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
required
adjustment_type
required
string
Enum: "increase" "decrease"
quantity
required
number >= 0.01

Always positive; direction is set by adjustment_type.

reason
string <= 100 characters
notes
string <= 500 characters

Responses

Request samples

Content type
application/json
{
  • "adjustment_type": "increase",
  • "quantity": 0.01,
  • "reason": "string",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Payments

✅ Read, record & refund available (record posts the receipt JE; INR only).

List payments

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 25

Page size (1–100).

cursor
string

Opaque cursor from the previous response's paging.next_cursor.

invoice_id
string
customer_id
string

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "paging": {
    }
}

Record a payment against an invoice

Records a payment and posts the receipt journal entry (DR bank/cash, CR the customer's receivable) as the in-app "Record Payment" does, then updates the invoice's paid/due/status. payment_mode_id chooses the bank/cash account — list options via GET /payments/{company}/methods.

Currency: only invoices whose currency is INR or unset are accepted; any other value returns 422. This is a hard INR check, not your company's base currency — a non-INR-base tenant cannot record payments against its own foreign-currency invoices via this endpoint.

The journal entry is best-effort: if the cash/bank account, the receivable account or the financial year can't be resolved, the payment is still recorded and journal_entry_id comes back null.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

header Parameters
Idempotency-Key
string <uuid>

A unique UUID so retries don't double‑create/charge/send. Cached 24h.

Request Body schema: application/json
required
invoice_id
required
string
amount
required
number >= 0.01

amount + tds_amount together must not exceed the invoice's due amount.

payment_date
required
string <date>
payment_mode_id
required
integer

From GET /payments/{company}/methods.

tds_amount
number >= 0

TDS withheld by the buyer. Counts toward settling the invoice alongside amount.

tds_section
string <= 40 characters
reference_number
string <= 100 characters
notes
string <= 500 characters

Responses

Request samples

Content type
application/json
{
  • "invoice_id": "string",
  • "amount": 0.01,
  • "payment_date": "2019-08-24",
  • "payment_mode_id": 0,
  • "tds_amount": 0,
  • "tds_section": "string",
  • "reference_number": "string",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List payment modes

Active payment modes for the company — use the returned id as payment_mode_id when recording a payment.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get a payment

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Refund (void) a payment

Reverses the payment — voids its journal entry and recomputes the invoice's paid/due/status. Full reversal only (partial refunds are not supported yet; no request body is read).

⚠️ The payment record is removed, not flagged. After a refund GET /payments/{company}/{id} returns 404, and refunding the same id twice also returns 404 — there is no refunded: true state to read back.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

header Parameters
Idempotency-Key
string <uuid>

A unique UUID so retries don't double‑create/charge/send. Cached 24h.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Messaging

✅ SMS, WhatsApp & Email available. Security‑sensitive — dedicated send scopes, lower rate limits and a daily cap. Path carries the company slug.

Send an SMS

Sends an SMS via the company's gateway. Requires the messages:sms:send scope. Subject to the messaging rate limit + daily cap.

India (DLT) — read this before you debug for an afternoon. Pass an approved sender_id plus its registered template_id (and pe_id), and make message match the approved template text exactly — including punctuation and any sender suffix (e.g. ... -ACMEID). Variables occupy the {#var#} slots. sender_id and template_id must be a matched pair: the template is registered against one sender.

⚠️ A mismatch fails silently. If message does not match the registered template, or template_id is missing/wrong, the carrier DROPS the message — but this endpoint still returns 202. It will look like it worked while nothing is ever delivered. 202 means accepted, not delivered (lifecycle: queued → submitted → delivered); confirm real delivery with GET /messaging/{company}/messages/{id}.

Your approved sender IDs, templates and PE ID are listed in Marketing → SMS Gateway (DLT Registration / Sender IDs / Templates).

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
to
required
string

Recipient number, digits only (8–15).

message
required
string <= 1000 characters
sender_id
string <= 11 characters

An APPROVED sender ID (Marketing → SMS Gateway → Sender IDs). Must be the sender the template_id is registered against.

template_id
string <= 64 characters

Registered DLT template id. Omit it and Indian carriers drop the SMS silently.

pe_id
string <= 64 characters

DLT principal entity (PE) id, from Marketing → SMS Gateway → DLT Registration.

type
string
Default: "transactional"
Enum: "transactional" "promotional"

Responses

Request samples

Content type
application/json
{
  • "to": "919800000000",
  • "message": "Your OTP is 123456",
  • "sender_id": "ACMEID",
  • "template_id": "1007487766981813506",
  • "pe_id": "1001609937061127455",
  • "type": "transactional"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Send a WhatsApp message

Sends via the company's Meta Cloud API provider. Business‑initiated messages must use a Meta‑APPROVED template; free text is only delivered inside an open 24‑hour customer‑service window. Requires the messages:whatsapp:send scope.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
to
required
string
type
string
Default: "template"
Enum: "template" "text"
object

Required when type=template.

object

Required when type=text.

Responses

Request samples

Content type
application/json
{
  • "to": "919800000000",
  • "type": "template",
  • "template": {
    },
  • "text": {
    }
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get message delivery status

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

The provider message id returned by a send call.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Send an email

Sends a transactional email through your company's configured email provider (Settings → Marketing → Email provider); if none is set the platform default mailer is used. The sender identity is taken from that provider — you cannot set an arbitrary from. HTML is sanitised server‑side (script/iframe/event‑handler vectors are stripped). Up to 50 recipients per call.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
required
Array of objects

One recipient or an array. Each item may be a plain email string or an object.

subject
required
string <= 255 characters
html
required
string

Email body as HTML. Sanitised server‑side before send.

Responses

Request samples

Content type
application/json
{
  • "to": [
    ],
  • "subject": "string",
  • "html": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Recruitment

✅ Available. Public, embeddable career‑site API.

List open jobs

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get a job

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

slug
required
string

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Submit an application

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

slug
required
string
Request Body schema: multipart/form-data
required
first_name
required
string <= 100 characters
last_name
string <= 100 characters
email
required
string <email> <= 255 characters
phone
string <= 30 characters
resume
required
string <binary>

Required. Allowed: pdf, doc, docx. Max 10 MB.

cover_letter
string <= 5000 characters
total_experience
number [ 0 .. 50 ]

Years.

expected_salary
number
notice_period_days
integer >= 0
linkedin_url
string <uri> <= 500 characters
skills
string

A JSON-encoded string (not an array), e.g. '["PHP","Vue"]'.

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

List departments

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Leads

✅ Available. Capture leads from external sites.

Capture a lead

Captures a lead. Send application/json, or multipart/form-data if you need to include an attachment file. Re-submitting an existing lead is de-duplicated server-side and still returns 200.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema:
required
first_name
required
string
last_name
required
string
email
required
string <email>
phone
string
company_name
string
lead_type
string
Enum: "contact" "rfp" "enquiry" "demo_request"
service
string
source
string
source_url
string <uri>
form_code
string
message
string <= 10000 characters
job_title
string
company_size
string
industry
string
country
string
services_needed
string
budget_range
string
timeline
string
project_overview
string
goals_expectations
string
current_systems
string
how_heard
string

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "company_name": "string",
  • "lead_type": "contact",
  • "service": "string",
  • "source": "string",
  • "source_url": "http://example.com",
  • "form_code": "string",
  • "message": "string",
  • "job_title": "string",
  • "company_size": "string",
  • "industry": "string",
  • "country": "string",
  • "services_needed": "string",
  • "budget_range": "string",
  • "timeline": "string",
  • "project_overview": "string",
  • "goals_expectations": "string",
  • "current_systems": "string",
  • "how_heard": "string"
}

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

List allowed lead sources

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Storefront

✅ Available. Headless storefront / checkout.

List catalog

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Get a catalog product

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

productId
required
string

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Create an order / checkout

Creates a sales order (document_type=sales_order, status draft) and starts a payment intent — it does not create an invoice, post a journal entry, or reserve or decrement stock. The order becomes a real invoice only after the payment gateway webhook confirms payment. A tenant customer is created (or matched by email, then by the last 9 digits of the phone) as a side effect.

Prices are server-authoritative when product_id is supplied: your unit_price and name are discarded and replaced with the catalogue values. They are only honoured for ad-hoc lines that omit product_id.

⚠️ This endpoint does not support idempotency — the Idempotency-Key header is ignored here, so a retry creates a duplicate order.

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
required
Array of objects [ 1 .. 50 ] items
required
object
currency
required
string = 3 characters
Enum: "INR" "USD" "EUR" "GBP" "AUD" "CAD" "SGD" "MYR"
source_website
required
string <= 255 characters
return_url
required
string <uri> <= 500 characters
cancel_url
required
string <uri> <= 500 characters
tax_amount
number
shipping_amount
number
notes
string
metadata
object

Responses

Request samples

Content type
application/json
{
  • "items": [
    ],
  • "customer": {
    },
  • "currency": "INR",
  • "source_website": "string",
  • "return_url": "http://example.com",
  • "cancel_url": "http://example.com",
  • "tax_amount": 0,
  • "shipping_amount": 0,
  • "notes": "string",
  • "metadata": { }
}

Response samples

Content type
application/json
{
  • "success": true,
  • "order_id": 0,
  • "order_number": "string",
  • "total_amount": 0,
  • "currency": "string",
  • "gateway": "razorpay",
  • "payment_data": { }
}

Order status

Returns an order created through this storefront checkout. Documents raised inside the app are not visible here and return 404, even though they live in the same company — this endpoint is deliberately scoped to storefront-origin orders only.

invoice_url stays null until the order converts to an invoice (i.e. until the payment webhook confirms payment).

Authorizations:
(ClientIdClientSecret)
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

orderId
required
string

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Bookings

✅ Available. Driving-school booking flow — service locations, instructors by suburb, lessons & packages, availability, and bookings with online payment. Accepts a secret key OR a browser publishable (pk_) key.

List service locations

Active service locations (test centres / pickup points / offices).

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "locations": [
    ]
}

Find instructors

Bookable instructors, optionally filtered to those who service a suburb/postcode/point.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
lat
number

Latitude (with lng) — distance match vs each instructor's radius_km.

lng
number

Longitude (with lat).

postcode
string

Instructors servicing this postcode.

suburb
string

Instructors servicing this suburb.

location_id
integer

Instructors mapped to this service location.

transmission
string
Enum: "auto" "manual" "both"

Instructor's transmission (a custom field — both is a real value).

gender
string

Case-insensitive exact match.

language
string

Instructor speaks this language.

nationality
string

Case-insensitive exact match.

car
string

Filter by the instructor's car.

available_date
string <date>

Only instructors with free capacity on this date.

time_of_day
string
Enum: "morning" "afternoon" "evening"

Narrows available_date to a part of the day.

with_next
boolean

Include each instructor's next_available slot in the response (costs an extra lookup).

cf
object

Match arbitrary instructor custom fields, e.g. cf[transmission]=auto. See GET /schools/{company}/instructor-fields for the available keys.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "instructors": [
    ]
}

List lessons & packages

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
transmission
string
Enum: "auto" "manual"
type
string
Enum: "lesson" "package"
instructor_id
integer

Only the lessons/packages this instructor actually offers.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "courses": [
    ]
}

Get available time slots

Bookable slots for an instructor on a date, honouring the weekly schedule, overrides, existing bookings and booking settings.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
instructor_id
required
integer
date
required
string <date>
duration_minutes
integer [ 15 .. 480 ]

Slot length to fit. Outside 15–480 returns 422.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "available": true,
  • "reason": "string",
  • "slots": [
    ]
}

List instructor filter fields

The custom-field definitions available for filtering instructors — use the returned key values with the cf[...] query parameter on GET /instructors to build facets without hard-coding them.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "fields": [
    ]
}

Look up a returning customer

Returns the stored name for a matching email or phone so the widget can greet a returning student and pre-fill the form. Pass email or phone.

⚠️ This confirms whether a given email/phone is a customer of the school and reveals their name. Its only gate is your key's allowed-origins list, so treat the key as origin-locked and do not ship it anywhere you would not accept that lookup being run.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
email
string <email>

Exact match.

phone
string

Digits are extracted, so formatting is ignored.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "customer": {
    }
}

Resolve a point to the nearest serviced suburb

Maps browser geolocation to a suburb you can feed back into GET /instructors?suburb=.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
lat
required
number [ -90 .. 90 ]
lng
required
number [ -180 .. 180 ]

Responses

Response samples

Content type
application/json
Example
{
  • "success": false,
  • "message": "Invalid API credentials, or the company was not found."
}

Quote the travel charge for a driving test

Prices the travel component for a test-day pickup before booking, so the widget can show it up front. The same charge is recomputed server-side when the booking is created.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

query Parameters
location_id
required
integer

The test centre. Must exist, else 422.

lat
required
number [ -90 .. 90 ]

Pickup latitude.

lng
required
number [ -180 .. 180 ]

Pickup longitude.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "currency": "AUD",
  • "travel_distance_km": 0,
  • "travel_charge": 0
}

Reserve a lesson package

Buys a lesson package for a customer, optionally scheduling its lessons up front and optionally taking a deposit (pay_amount) rather than the full price. Supply return_url+cancel_url to start online payment and receive payment_data.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
required
object (SchoolCustomer)

Buyer details for the schools flows. phone is required and email is optional — note this is the opposite of most of the API.

product_id
required
integer

Must be a lesson package, else 422.

lessons
Array of objects <= 50 items

Optional lessons to schedule now. Each must be at least 15 minutes.

pay_amount
number or null >= 0

Deposit. Omit to charge the full package price.

return_url
string or null <uri>
cancel_url
string or null <uri>

Responses

Request samples

Content type
application/json
{
  • "customer": {
    },
  • "product_id": 0,
  • "lessons": [
    ],
  • "pay_amount": 0,
  • "return_url": "http://example.com",
  • "cancel_url": "http://example.com"
}

Response samples

Content type
application/json
{
  • "success": true,
  • "message": "string",
  • "booking": {
    },
  • "payment": {
    }
}

Reserve an order of services

Orders one or more services from an instructor's menu (up to 20 items), optionally with a deposit. Supply return_url+cancel_url to start online payment.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
required
object (SchoolCustomer)

Buyer details for the schools flows. phone is required and email is optional — note this is the opposite of most of the API.

instructor_id
required
integer
items
required
Array of objects [ 1 .. 20 ] items

Services from this instructor's menu. An unavailable service returns 422.

pay_amount
number or null >= 0

Deposit. Omit to charge the full total.

payment_method
string or null
Enum: "card" "bank_transfer"
return_url
string or null <uri>
cancel_url
string or null <uri>

Responses

Request samples

Content type
application/json
{
  • "customer": {
    },
  • "instructor_id": 0,
  • "items": [
    ],
  • "pay_amount": 0,
  • "payment_method": "card",
  • "return_url": "http://example.com",
  • "cancel_url": "http://example.com"
}

Response samples

Content type
application/json
{
  • "success": true,
  • "message": "string",
  • "booking": {
    },
  • "payment": {
    }
}

Create a booking

Match/create the customer and create the booking. If return_url+cancel_url are supplied and payment is due, payment is initiated and payment_url returned. Prices come from your catalogue server-side.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

Request Body schema: application/json
required
required
object (SchoolCustomer)

Buyer details for the schools flows. phone is required and email is optional — note this is the opposite of most of the API.

instructor_id
required
integer

Must exist — an unknown id is 422, not 404.

product_id
integer or null
service_location_id
integer or null
booking_package_id
integer or null

Book against a pre-paid package (no payment). 403 if the package belongs to another customer.

booking_date
required
string <date>

Today or later — a past date is rejected.

start_time
string or null^\d{2}:\d{2}$

24-hour HH:MM. Required unless test_time is given.

end_time
string or null^\d{2}:\d{2}$

24-hour HH:MM. Must be after start_time.

duration_minutes
integer or null [ 15 .. 480 ]
test_time
string or null^\d{2}:\d{2}$

24-hour HH:MM. Sending this makes it a DRIVING-TEST booking; the block is derived from this time.

lesson_before_minutes
integer or null
Enum: 0 45 60 90 120

Warm-up lesson immediately before the test.

pickup_required
boolean or null

Test-day pickup. The pickup coordinates drive the travel charge.

pickup_lat
number or null [ -90 .. 90 ]
pickup_lng
number or null [ -180 .. 180 ]
pickup_address
string or null <= 500 characters
dropoff_address
string or null <= 500 characters
student_notes
string or null <= 1000 characters
return_url
string or null <uri>

Supply BOTH urls to initiate online payment immediately — the response then carries payment_data/payment_url.

cancel_url
string or null <uri>

Responses

Request samples

Content type
application/json
{
  • "customer": {
    },
  • "instructor_id": 0,
  • "product_id": 0,
  • "service_location_id": 0,
  • "booking_package_id": 0,
  • "booking_date": "2019-08-24",
  • "start_time": "10:00",
  • "end_time": "12:00",
  • "duration_minutes": 15,
  • "test_time": "14:30",
  • "lesson_before_minutes": 0,
  • "pickup_required": true,
  • "pickup_lat": -90,
  • "pickup_lng": -180,
  • "pickup_address": "string",
  • "dropoff_address": "string",
  • "student_notes": "string",
  • "return_url": "http://example.com",
  • "cancel_url": "http://example.com"
}

Response samples

Content type
application/json
{
  • "success": true,
  • "message": "string",
  • "booking": {
    },
  • "payment": {
    }
}

Start/retry online payment

Initiate payment for a pending, unpaid booking that this widget created. Returns payment_url/payment_data to redirect to; the booking is confirmed by the gateway webhook on success. The amount is derived server-side — there is no amount or payment-mode field. Requires a configured gateway for the currency, else 422.

Only widget-created, still-pending bookings are payable: handing this any other booking id in the tenant returns 403, not a checkout.

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Request Body schema: application/json
required
return_url
required
string <uri>
cancel_url
required
string <uri>

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "success": true,
  • "message": "string",
  • "booking": {
    },
  • "payment": {
    }
}

Get booking status

Authorizations:
(ClientIdClientSecret) PublishableKey
path Parameters
company
required
string
Example: acme-traders

Your company (workspace) slug — the same value as your {slug}.laabam.app subdomain, shown in Settings → Company Profile. It is not your display name, brand or product name: a company shown as “Acme Traders” has the slug acme-traders.

An unknown slug returns 401 with the same body as a bad key — Invalid API credentials, or the company was not found. The two cases are intentionally indistinguishable so nobody can probe which company slugs exist without valid credentials. If you get that 401, check both the slug and the key.

id
required
string

Opaque resource identifier.

Responses

Response samples

Content type
application/json
{
  • "success": true,
  • "booking": {
    }
}