Quick Start

Watch a walkthrough of how to authenticate and make your first API call.

Authentication

The Landlord API uses API keys to authenticate requests. You can manage your API keys from the Settings > Developer page.

Include your secret key in the Authorization header of every request.

Your API key carries access to your organization's data — keep it secret. Do not share it in client-side code or public repositories. All API requests must be made over HTTPS.

Public IDs — Every resource has a prefixed public ID: fac_ Facility, cus_ User, sub_ Subscription, prd_ Product, prm_ Promotion, utp_ Unit Type, unt_ Unit, fee_ Fee. Facility IDs are found on Settings > Developer.

Example Request
curl https://your-domain.com/api/v1/invoices \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx"

Your API Key

sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Errors

Landlord uses conventional HTTP response codes. Codes in the 2xx range indicate success. Codes in the 4xx range indicate a client error. Codes in the 5xx range indicate a server error.

Error Types

authentication_errorstring

Invalid or missing API key

invalid_request_errorstring

The request was malformed or contained invalid parameters

api_errorstring

An internal server error occurred

HTTP Status Codes

200

OK — Request succeeded

201

Created — Resource created successfully

400

Bad Request — Invalid parameters

401

Unauthorized — Invalid or missing API key

404

Not Found — Resource does not exist

429

Too Many Requests — Rate limit exceeded

500

Internal Server Error

Error Response
{
  "error": {
    "type": "invalid_request_error",
    "message": "No such invoice.",
    "param": "id"
  }
}

Rate Limiting

The API enforces a rate limit of 100 requests per minute per API key. When exceeded, the API returns a 429 status code with a Retry-After header.

Rate Limit

100requests / minute / key

Pagination

All list endpoints support cursor-based pagination.

limitinteger

Number of results to return (default 25, max 100)

starting_afterstring

Cursor for pagination. Pass the id of the last item in the previous page.

Response Format
{
  "object": "list",
  "data": [ "..." ],
  "has_more": true
}
Paginating Results
# First page
curl https://your-domain.com/api/v1/invoices?limit=10 \
  -H "Authorization: Bearer sk_live_..."

# Next page
curl https://your-domain.com/api/v1/invoices?limit=10&starting_after=42 \
  -H "Authorization: Bearer sk_live_..."

Expanding Responses

Some endpoints support expanding nested objects using the expand parameter.

Supported Expansions

GET /v1/users/{id}

invoices, subscriptions

Expanding Fields
curl "https://your-domain.com/api/v1/users/cus_aBcDeFgHiJkLmNoPqRsTuVwX?expand[]=invoices&expand[]=subscriptions" \
  -H "Authorization: Bearer sk_live_..."
Expanded Response
{
  "id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "user",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "invoices": [
    {
      "id": 101,
      "object": "invoice",
      "status": "open",
      "total": 1500.00,
      "currency": "USD",
      "due_date": "2026-03-15T00:00:00+00:00"
    }
  ],
  "subscriptions": [
    {
      "id": "sub_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "subscription",
      "status": "active",
      "current_price": 150.00,
      "billing_interval": "month"
    }
  ]
}

Invoices

Invoices represent one-time or recurring charges to a tenant. You can optionally include a payment_url — an external link where the tenant can pay.

The Invoice Object

The Invoice Object
{
  "id": 42,
  "object": "invoice",
  "invoice_number": "INV-000042",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "subscription_id": null,
  "status": "open",
  "display_status": "unpaid",
  "type": "other",
  "description": "March Rent",
  "line_items": [
    {
      "description": "March Rent",
      "quantity": 1,
      "unit_price": 1500.00,
      "amount": 1500.00
    }
  ],
  "subtotal": 1500.00,
  "total_tax": 0.00,
  "total": 1500.00,
  "amount_paid": 0.00,
  "amount_remaining": 1500.00,
  "currency": "USD",
  "due_date": "2026-03-15T00:00:00+00:00",
  "paid_at": null,
  "voided_at": null,
  "payment_url": "https://pay.example.com/inv/abc123",
  "payment_reference": "ref_abc123",
  "metadata": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

List all invoices

GET/v1/invoices
facility_idstring

Filter by facility (public ID)

user_idstring

Filter by tenant (public user ID)

statusstring

Filter by status (open, paid, void, pending)

limitinteger

Max results (default 25, max 100)

starting_afterinteger

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/invoices?status=open&limit=10 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": 42,
      "object": "invoice",
      "invoice_number": "INV-000042",
      "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
      "status": "open",
      "total": 1500.00,
      "currency": "USD",
      "due_date": "2026-03-15T00:00:00+00:00"
    }
  ],
  "has_more": false
}

Retrieve an invoice

GET/v1/invoices/{id}

Retrieves an invoice by its ID.

Example Request
curl https://your-domain.com/api/v1/invoices/42 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": 42,
  "object": "invoice",
  "invoice_number": "INV-000042",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "status": "open",
  "display_status": "unpaid",
  "type": "other",
  "description": "March Rent",
  "subtotal": 1500.00,
  "total_tax": 0.00,
  "total": 1500.00,
  "amount_paid": 0.00,
  "amount_remaining": 1500.00,
  "currency": "USD",
  "due_date": "2026-03-15T00:00:00+00:00",
  "paid_at": null,
  "voided_at": null,
  "payment_url": "https://pay.example.com/inv/abc123",
  "payment_reference": "ref_abc123",
  "metadata": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

Create an invoice

POST/v1/invoices
user_idstringrequired

Public user ID (prefixed with cus_)

amountnumberrequired

Charge amount (before tax)

facility_idstring

Public facility ID (defaults to first in org)

descriptionstring

Invoice description (default: "API Invoice")

typestring

Invoice type (default: other)

currencystring

Currency code (default: facility currency)

tax_ratenumber

Tax percentage (default: 0)

days_until_dueinteger

Days until due (default: 7)

payment_urlstring

External payment link for the tenant

metadataobject

Arbitrary key-value data

fee_idsarray

Array of fee IDs (prefixed with fee_) to attach. Sales tax fees add to total_tax; deposit/setup fees add to subtotal.

Example Request
curl https://your-domain.com/api/v1/invoices \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
    "amount": 1500.00,
    "description": "March Rent",
    "payment_url": "https://pay.example.com/inv/abc123",
    "days_until_due": 14,
    "fee_ids": ["fee_aBcDeFgHiJkLmNoPqRsTuVwX"],
    "metadata": {
      "external_id": "inv_12345"
    }
  }'
Response
{
  "id": 43,
  "object": "invoice",
  "invoice_number": "INV-000043",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "status": "open",
  "display_status": "unpaid",
  "type": "other",
  "description": "March Rent",
  "subtotal": 1500.00,
  "total_tax": 0.00,
  "total": 1500.00,
  "amount_paid": 0.00,
  "amount_remaining": 1500.00,
  "currency": "USD",
  "due_date": "2026-03-19T00:00:00+00:00",
  "paid_at": null,
  "voided_at": null,
  "payment_url": "https://pay.example.com/inv/abc123",
  "payment_reference": null,
  "metadata": {
    "external_id": "inv_12345"
  },
  "created_at": "2026-03-05T12:00:00+00:00",
  "updated_at": "2026-03-05T12:00:00+00:00"
}

Update an invoice

PATCH/v1/invoices/{id}
descriptionstring

Update description

payment_urlstring

Update or set external payment link

metadataobject

Update metadata

statusstring

Transition to open, paid, or void

When setting status to paid, the amount_paid is automatically set to the full total and paid_at is recorded.

Mark as Paid
curl -X PATCH https://your-domain.com/api/v1/invoices/42 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"status": "paid"}'
Response
{
  "id": 42,
  "object": "invoice",
  "status": "paid",
  "display_status": "paid",
  "total": 1500.00,
  "amount_paid": 1500.00,
  "amount_remaining": 0.00,
  "paid_at": "2026-03-05T14:30:00+00:00",
  "updated_at": "2026-03-05T14:30:00+00:00"
}

Delete an invoice

DELETE/v1/invoices/{id}

Voids the invoice. Paid invoices cannot be deleted.

Example Request
curl -X DELETE https://your-domain.com/api/v1/invoices/42 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Subscriptions

Subscriptions represent recurring billing schedules for tenants (e.g. monthly rent).

The Subscription Object

The Subscription Object
{
  "id": "sub_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "subscription",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "product_id": null,
  "unit_id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_name": "A-22",
  "subscription_type": "rental",
  "status": "active",
  "base_price": 1500.00,
  "current_price": 1500.00,
  "tax_rate": 0.00,
  "price_with_tax": 1500.00,
  "has_discount": false,
  "discount_type": null,
  "discount_amount": null,
  "billing_interval": "month",
  "billing_interval_count": 1,
  "current_period_start": "2026-03-01T00:00:00+00:00",
  "current_period_end": "2026-04-01T00:00:00+00:00",
  "next_bill_date": "2026-04-01T00:00:00+00:00",
  "move_in_date": "2026-03-01T00:00:00+00:00",
  "move_out_date": null,
  "cancel_at": null,
  "canceled_at": null,
  "display_name": "Rent - A-22",
  "days_until_due": 7,
  "metadata": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

List all subscriptions

GET/v1/subscriptions
facility_idstring

Filter by facility (public ID)

user_idstring

Filter by tenant (public user ID)

statusstring

Filter by status

limitinteger

Max results (default 25, max 100)

starting_afterinteger

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/subscriptions?user_id=15 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "sub_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "subscription",
      "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
      "status": "active",
      "base_price": 1500.00,
      "billing_interval": "month",
      "display_name": "Unit A-22 Rent"
    }
  ],
  "has_more": false
}

Retrieve a subscription

GET/v1/subscriptions/{id}

Retrieves a subscription by its ID.

Example Request
curl https://your-domain.com/api/v1/subscriptions/7 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "sub_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "subscription",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_name": "A-22",
  "subscription_type": "rental",
  "status": "active",
  "base_price": 1500.00,
  "current_price": 1500.00,
  "tax_rate": 0.00,
  "price_with_tax": 1500.00,
  "billing_interval": "month",
  "billing_interval_count": 1,
  "next_bill_date": "2026-04-01T00:00:00+00:00",
  "display_name": "Rent - A-22",
  "days_until_due": 7,
  "metadata": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

Create a subscription

POST/v1/subscriptions
user_idstringrequired

Public user ID (prefixed with cus_)

base_pricenumberrequired

Recurring charge amount

facility_idstring

Public facility ID (defaults to first in org)

subscription_typestring

Type (default: rental). Accepts rental or rent.

product_idstring

Product ID (prefixed with prd_)

unit_idstring

Unit ID (prefixed with unt_). Required for rental subscriptions. Creates a rental record and marks the unit as rented.

unit_namestring

Unit name for display. Auto-populated from the unit if not provided.

statusstring

Initial status (default: active)

tax_ratenumber

Tax percentage (default: 0)

billing_intervalstring

month, year, week, day (default: month)

billing_interval_countinteger

Intervals per cycle (default: 1)

current_period_startstring

ISO 8601 date (default: move-in date)

current_period_endstring

ISO 8601 date (default: next bill date)

next_bill_datestring

Auto-calculated as one billing interval from move-in date if not provided

move_in_datestring

ISO 8601 date (default: today)

days_until_dueinteger

Default: 7

display_namestring

Auto-set to "Rent - {unit_name}" for rentals if not provided

metadataobject

Arbitrary key-value data

fee_idsarray

Array of fee IDs (prefixed with fee_). Sales tax fees set tax_rate; deposit/setup fees create one-time invoices.

Example Request
curl https://your-domain.com/api/v1/subscriptions \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
    "unit_id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
    "base_price": 1500.00,
    "billing_interval": "month",
    "fee_ids": ["fee_aBcDeFgHiJkLmNoPqRsTuVwX"]
  }'
Response
{
  "id": "sub_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "subscription",
  "user_id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_name": "A-22",
  "subscription_type": "rental",
  "status": "active",
  "base_price": 1500.00,
  "current_price": 1500.00,
  "billing_interval": "month",
  "next_bill_date": "2026-04-01T00:00:00+00:00",
  "display_name": "Rent - A-22",
  "created_at": "2026-03-05T12:00:00+00:00",
  "updated_at": "2026-03-05T12:00:00+00:00"
}

Update a subscription

PATCH/v1/subscriptions/{id}

Updatable fields: status, base_price, current_price, tax_rate, billing_interval, next_bill_date, display_name, unit_name, metadata, and more.

When updating base_price, current_price and price_with_tax are recalculated automatically.

Example Request
curl -X PATCH https://your-domain.com/api/v1/subscriptions/7 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"base_price": 1600.00}'
Response
{
  "id": "sub_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "subscription",
  "status": "active",
  "base_price": 1600.00,
  "current_price": 1600.00,
  "price_with_tax": 1600.00,
  "updated_at": "2026-03-05T14:30:00+00:00"
}

Cancel a subscription

DELETE/v1/subscriptions/{id}

Sets the subscription status to canceled and records canceled_at.

Example Request
curl -X DELETE https://your-domain.com/api/v1/subscriptions/7 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Users

Users represent tenants (customers) at your facilities.

The User Object

The User Object
{
  "id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "user",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "locale": "en",
  "phone_verified": false,
  "email_verified": true,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

List all users

GET/v1/users
facility_idstring

Filter by facility (public ID)

emailstring

Filter by exact email

limitinteger

Max results (default 25, max 100)

starting_afterinteger

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/users?email=jane@example.com \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "user",
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
      "locale": "en"
    }
  ],
  "has_more": false
}

Retrieve a user

GET/v1/users/{id}

Supports expand parameter for invoices and subscriptions.

Example with Expand
curl "https://your-domain.com/api/v1/users/cus_aBcDeFgHiJkLmNoPqRsTuVwX?expand[]=invoices&expand[]=subscriptions" \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "user",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "locale": "en",
  "phone_verified": false,
  "email_verified": true,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

Create a user

POST/v1/users
emailstringrequired

Email address (must be unique per facility)

facility_idstring

Public facility ID (defaults to first in org)

first_namestring

First name

last_namestring

Last name

passwordstring

Password (auto-generated if not provided)

localestring

Language preference (default: en)

Example Request
curl https://your-domain.com/api/v1/users \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX"
  }'
Response
{
  "id": 16,
  "object": "user",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "locale": "en",
  "phone_verified": false,
  "email_verified": false,
  "created_at": "2026-03-05T12:00:00+00:00",
  "updated_at": "2026-03-05T12:00:00+00:00"
}

Update a user

PATCH/v1/users/{id}

Updatable fields: first_name, last_name, email, locale

Example Request
curl -X PATCH https://your-domain.com/api/v1/users/cus_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"first_name": "Janet"}'
Response
{
  "id": "cus_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "user",
  "first_name": "Janet",
  "last_name": "Doe",
  "email": "jane@example.com",
  "locale": "en",
  "updated_at": "2026-03-05T14:30:00+00:00"
}

Delete a user

DELETE/v1/users/{id}

Soft-deletes the user. The user record is preserved but marked as deleted.

Example Request
curl -X DELETE https://your-domain.com/api/v1/users/cus_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Products

Products represent billable items that can be offered to tenants (e.g. tenant protection plans, parking spots, boxes).

The Product Object

The Product Object
{
  "id": "prd_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "product",
  "name": "Tenant Protection Plan",
  "description": "Covers up to $5,000 in damages",
  "price": 15.00,
  "sales_tax_value": 0.00,
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "is_for_new_customers": true,
  "is_tenant_protection": true,
  "is_one_time_purchase": false,
  "offer_in_pipeline": true,
  "singular_purchase": true,
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-01-10T08:00:00+00:00",
  "updated_at": "2026-01-10T08:00:00+00:00"
}

List all products

GET/v1/products
facility_idstring

Filter by facility (public ID)

limitinteger

Max results (default 25, max 100)

starting_afterinteger

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/products \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "prd_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "product",
      "name": "Tenant Protection Plan",
      "price": 15.00,
      "billing_interval": "month",
      "is_one_time_purchase": false
    }
  ],
  "has_more": false
}

Retrieve a product

GET/v1/products/{id}

Retrieves a product by its ID.

Example Request
curl https://your-domain.com/api/v1/products/5 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "prd_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "product",
  "name": "Tenant Protection Plan",
  "description": "Covers up to $5,000 in damages",
  "price": 15.00,
  "sales_tax_value": 0.00,
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "is_for_new_customers": true,
  "is_tenant_protection": true,
  "is_one_time_purchase": false,
  "offer_in_pipeline": true,
  "singular_purchase": true,
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-01-10T08:00:00+00:00",
  "updated_at": "2026-01-10T08:00:00+00:00"
}

Create a product

POST/v1/products
namestringrequired

Product name

facility_idstring

Public facility ID (defaults to first in org)

descriptionstring

Description

pricenumber

Price (default: 0)

sales_tax_valuenumber

Tax rate (default: 0)

is_one_time_purchaseboolean

One-time charge (default: false)

billing_intervalstring

Default: month

billing_interval_countinteger

Default: 1

offer_in_pipelineboolean

Show in onboarding (default: false)

Example Request
curl https://your-domain.com/api/v1/products \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Parking Spot",
    "price": 50.00,
    "billing_interval": "month",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX"
  }'
Response
{
  "id": "prd_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "product",
  "name": "Parking Spot",
  "description": null,
  "price": 50.00,
  "sales_tax_value": 0.00,
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "is_one_time_purchase": false,
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-03-05T12:00:00+00:00",
  "updated_at": "2026-03-05T12:00:00+00:00"
}

Update a product

PATCH/v1/products/{id}

Updatable fields: name, description, price, sales_tax_value, is_one_time_purchase, offer_in_pipeline, billing_interval, and more.

Example Request
curl -X PATCH https://your-domain.com/api/v1/products/5 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"price": 20.00}'
Response
{
  "id": "prd_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "product",
  "name": "Tenant Protection Plan",
  "price": 20.00,
  "updated_at": "2026-03-05T14:30:00+00:00"
}

Delete a product

DELETE/v1/products/{id}

Soft-deletes the product.

Example Request
curl -X DELETE https://your-domain.com/api/v1/products/5 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Promotions

Promotions define discounts that can be applied to subscriptions.

The Promotion Object

The Promotion Object
{
  "id": "prm_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "promotion",
  "name": "First Month Free",
  "description": "100% off first month of rent",
  "terms_and_conditions": "New tenants only. Cannot be combined.",
  "discount_type": "percentage",
  "discount_amount": 100.00,
  "duration_months": 1,
  "is_unlimited_duration": false,
  "count_partial_as_full": false,
  "start_date": "2026-01-01",
  "end_date": "2026-12-31",
  "is_active": true,
  "created_at": "2026-01-01T00:00:00+00:00",
  "updated_at": "2026-01-01T00:00:00+00:00"
}

List all promotions

GET/v1/promotions
is_activeboolean

Filter by active status

limitinteger

Max results (default 25, max 100)

starting_afterinteger

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/promotions?is_active=true \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "prm_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "promotion",
      "name": "First Month Free",
      "discount_type": "percentage",
      "discount_amount": 100.00,
      "is_active": true
    }
  ],
  "has_more": false
}

Retrieve a promotion

GET/v1/promotions/{id}

Retrieves a promotion by its ID.

Example Request
curl https://your-domain.com/api/v1/promotions/2 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "prm_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "promotion",
  "name": "First Month Free",
  "description": "100% off first month of rent",
  "terms_and_conditions": "New tenants only. Cannot be combined.",
  "discount_type": "percentage",
  "discount_amount": 100.00,
  "duration_months": 1,
  "is_unlimited_duration": false,
  "start_date": "2026-01-01",
  "end_date": "2026-12-31",
  "is_active": true,
  "created_at": "2026-01-01T00:00:00+00:00",
  "updated_at": "2026-01-01T00:00:00+00:00"
}

Create a promotion

POST/v1/promotions
namestringrequired

Promotion name

discount_typestringrequired

percentage or fixed

discount_amountnumberrequired

Discount value

descriptionstring

Description

terms_and_conditionsstring

Legal terms

duration_monthsinteger

Duration in months

is_unlimited_durationboolean

Never expires (default: false)

start_datestring

ISO 8601 or YYYY-MM-DD

end_datestring

ISO 8601 or YYYY-MM-DD

is_activeboolean

Default: true

Example Request
curl https://your-domain.com/api/v1/promotions \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "50% Off First 3 Months",
    "discount_type": "percentage",
    "discount_amount": 50,
    "duration_months": 3,
    "start_date": "2026-03-01",
    "end_date": "2026-06-30"
  }'
Response
{
  "id": "prm_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "promotion",
  "name": "50% Off First 3 Months",
  "discount_type": "percentage",
  "discount_amount": 50.00,
  "duration_months": 3,
  "is_active": true,
  "start_date": "2026-03-01",
  "end_date": "2026-06-30",
  "created_at": "2026-03-05T12:00:00+00:00",
  "updated_at": "2026-03-05T12:00:00+00:00"
}

Update a promotion

PATCH/v1/promotions/{id}

Updatable fields: name, description, discount_type, discount_amount, duration_months, is_active, and more.

Example Request
curl -X PATCH https://your-domain.com/api/v1/promotions/2 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'
Response
{
  "id": "prm_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "promotion",
  "name": "First Month Free",
  "is_active": false,
  "updated_at": "2026-03-05T14:30:00+00:00"
}

Delete a promotion

DELETE/v1/promotions/{id}

Soft-deletes the promotion.

Example Request
curl -X DELETE https://your-domain.com/api/v1/promotions/2 \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Unit Types

Unit types define the sizes and pricing for storage units at a facility.

The Unit Type Object

The Unit Type Object
{
  "id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit_type",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "10x10 Standard",
  "price": 150.00,
  "length": 10,
  "width": 10,
  "height": 8,
  "measurement_unit": "ft",
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-01-15T10:00:00+00:00"
}

List all unit types

GET/v1/unit-types
facility_idstring

Filter by facility (public ID)

limitinteger

Max results (default 25, max 100)

starting_afterstring

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/unit-types?facility_id=fac_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "unit_type",
      "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
      "name": "10x10 Standard",
      "price": 150.00,
      "measurement_unit": "ft"
    }
  ],
  "has_more": false
}

Retrieve a unit type

GET/v1/unit-types/{id}

Retrieves a unit type by its ID.

Example Request
curl https://your-domain.com/api/v1/unit-types/utp_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit_type",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "10x10 Standard",
  "price": 150.00,
  "length": 10,
  "width": 10,
  "height": 8,
  "measurement_unit": "ft",
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-01-15T10:00:00+00:00"
}

Create a unit type

POST/v1/unit-types
namestringrequired

Unit type name

pricenumberrequired

Monthly price

facility_idstring

Public facility ID (defaults to first in org)

lengthnumber

Length dimension

widthnumber

Width dimension

heightnumber

Height dimension

measurement_unitstring

ft, m, in, or cm (default: ft)

billing_intervalstring

Default: month

billing_interval_countinteger

Default: 1

Example Request
curl https://your-domain.com/api/v1/unit-types \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "10x10 Standard",
    "price": 150.00,
    "length": 10,
    "width": 10,
    "height": 8,
    "measurement_unit": "ft",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX"
  }'
Response
{
  "id": "utp_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "unit_type",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "10x10 Standard",
  "price": 150.00,
  "length": 10,
  "width": 10,
  "height": 8,
  "measurement_unit": "ft",
  "billing_interval": "month",
  "billing_interval_count": 1,
  "created_at": "2026-03-06T12:00:00+00:00",
  "updated_at": "2026-03-06T12:00:00+00:00"
}

Update a unit type

PATCH/v1/unit-types/{id}

Updatable fields: name, price, length, width, height, measurement_unit, billing_interval, billing_interval_count

Example Request
curl -X PATCH https://your-domain.com/api/v1/unit-types/utp_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"price": 175.00}'
Response
{
  "id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit_type",
  "name": "10x10 Standard",
  "price": 175.00,
  "updated_at": "2026-03-06T14:30:00+00:00"
}

Delete a unit type

DELETE/v1/unit-types/{id}

Soft-deletes the unit type.

Example Request
curl -X DELETE https://your-domain.com/api/v1/unit-types/utp_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Units

Units represent individual storage spaces within a facility. Each unit belongs to a unit type.

The Unit Object

The Unit Object
{
  "id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_type_id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "A101",
  "status": "available",
  "floor_level": 1,
  "notes": null,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-01-15T10:00:00+00:00"
}

List all units

GET/v1/units
facility_idstring

Filter by facility (public ID)

unit_type_idstring

Filter by unit type (public ID)

statusstring

Filter by status (available, rented, moving out, unavailable)

limitinteger

Max results (default 25, max 100)

starting_afterstring

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/units?facility_id=fac_aBcDeFgHiJkLmNoPqRsTuVwX&status=available \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "unit",
      "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
      "unit_type_id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
      "name": "A101",
      "status": "available"
    }
  ],
  "has_more": false
}

Retrieve a unit

GET/v1/units/{id}

Retrieves a unit by its ID.

Example Request
curl https://your-domain.com/api/v1/units/unt_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_type_id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "A101",
  "status": "available",
  "floor_level": 1,
  "notes": null,
  "created_at": "2026-01-15T10:00:00+00:00",
  "updated_at": "2026-01-15T10:00:00+00:00"
}

Create a unit

POST/v1/units
unit_type_idstringrequired

Public unit type ID (prefixed with utp_)

namestringrequired

Unit name or number

facility_idstring

Public facility ID (defaults to first in org)

statusstring

Default: available

floor_levelinteger

Floor number

notesstring

Internal notes

Example Request
curl https://your-domain.com/api/v1/units \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "unit_type_id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
    "name": "A101",
    "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
    "floor_level": 1
  }'
Response
{
  "id": "unt_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "unit",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "unit_type_id": "utp_aBcDeFgHiJkLmNoPqRsTuVwX",
  "name": "A101",
  "status": "available",
  "floor_level": 1,
  "notes": null,
  "created_at": "2026-03-06T12:00:00+00:00",
  "updated_at": "2026-03-06T12:00:00+00:00"
}

Update a unit

PATCH/v1/units/{id}

Updatable fields: name, unit_type_id, status, floor_level, notes

Example Request
curl -X PATCH https://your-domain.com/api/v1/units/unt_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"status": "rented"}'
Response
{
  "id": "unt_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "unit",
  "name": "A101",
  "status": "rented",
  "updated_at": "2026-03-06T14:30:00+00:00"
}

Delete a unit

DELETE/v1/units/{id}

Soft-deletes the unit.

Example Request
curl -X DELETE https://your-domain.com/api/v1/units/unt_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Fees

Fees represent taxes and charges that can be applied to invoices and subscriptions. Fee types include sales tax, deposits, setup fees, and late fees.

The Fee Object

Fee Types

sales_taxSales Tax

Always percentage

depositSecurity Deposit

Fixed or percentage

setup_feeOne-time Setup Fee

Fixed or percentage

late_feeLate Fee

Fixed or percentage

The Fee Object
{
  "id": "fee_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "fee",
  "name": "State Sales Tax",
  "type": "sales_tax",
  "amount": 8.5,
  "calculation_type": "percentage",
  "days_late_until_charged": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

List all fees

GET/v1/fees
typestring

Filter by fee type (sales_tax, deposit, setup_fee, late_fee)

limitinteger

Max results (default 25, max 100)

starting_afterstring

Cursor for pagination

Example Request
curl https://your-domain.com/api/v1/fees?type=sales_tax \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "fee_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "fee",
      "name": "State Sales Tax",
      "type": "sales_tax",
      "amount": 8.5,
      "calculation_type": "percentage",
      "days_late_until_charged": null,
      "created_at": "2026-03-01T12:00:00+00:00",
      "updated_at": "2026-03-01T12:00:00+00:00"
    }
  ],
  "has_more": false
}

Retrieve a fee

GET/v1/fees/{id}

Retrieves a fee by its public ID.

Example Request
curl https://your-domain.com/api/v1/fees/fee_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "fee_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "fee",
  "name": "State Sales Tax",
  "type": "sales_tax",
  "amount": 8.5,
  "calculation_type": "percentage",
  "days_late_until_charged": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-01T12:00:00+00:00"
}

Create a fee

POST/v1/fees
namestringrequired

Fee name

typestringrequired

Fee type: sales_tax, deposit, setup_fee, or late_fee

amountnumberrequired

Fee amount

calculation_typestring

percentage or fixed. Defaults to percentage for sales_tax, fixed for others.

days_late_until_chargedinteger

Required for late_fee type. Days overdue before fee applies.

Example Request
curl https://your-domain.com/api/v1/fees \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "State Sales Tax",
    "type": "sales_tax",
    "amount": 8.5
  }'
Response
{
  "id": "fee_xYzAbCdEfGhIjKlMnOpQrStUv",
  "object": "fee",
  "name": "State Sales Tax",
  "type": "sales_tax",
  "amount": 8.5,
  "calculation_type": "percentage",
  "days_late_until_charged": null,
  "created_at": "2026-03-06T12:00:00+00:00",
  "updated_at": "2026-03-06T12:00:00+00:00"
}

Update a fee

PATCH/v1/fees/{id}
namestring

Update fee name

amountnumber

Update fee amount

calculation_typestring

Update calculation type

days_late_until_chargedinteger

Update days late threshold

Example Request
curl -X PATCH https://your-domain.com/api/v1/fees/fee_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"amount": 9.0}'
Response
{
  "id": "fee_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "fee",
  "name": "State Sales Tax",
  "type": "sales_tax",
  "amount": 9.0,
  "calculation_type": "percentage",
  "days_late_until_charged": null,
  "created_at": "2026-03-01T12:00:00+00:00",
  "updated_at": "2026-03-06T14:30:00+00:00"
}

Delete a fee

DELETE/v1/fees/{id}

Deletes the fee.

Example Request
curl -X DELETE https://your-domain.com/api/v1/fees/fee_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "deleted": true
}

Facilities

Facilities represent physical storage locations in your organization. Use these endpoints to list facilities and retrieve dashboard-style analytics.

The Facility Object

The Facility Object
{
  "id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "facility",
  "name": "Downtown Storage",
  "slug": "downtown-storage",
  "total_units": 120,
  "active_rentals": 98,
  "occupancy_rate": 81.7,
  "created_at": "2025-06-15T10:00:00+00:00",
  "updated_at": "2026-02-01T14:30:00+00:00"
}

List all facilities

GET/v1/facilities

Returns all facilities in your organization.

Example Request
curl https://your-domain.com/api/v1/facilities \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "list",
  "data": [
    {
      "id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
      "object": "facility",
      "name": "Downtown Storage",
      "slug": "downtown-storage",
      "total_units": 120,
      "active_rentals": 98,
      "occupancy_rate": 81.7,
      "created_at": "2025-06-15T10:00:00+00:00",
      "updated_at": "2026-02-01T14:30:00+00:00"
    }
  ],
  "has_more": false
}

Retrieve a facility

GET/v1/facilities/{id}

Returns a single facility by its public ID.

Example Request
curl https://your-domain.com/api/v1/facilities/fac_aBcDeFgHiJkLmNoPqRsTuVwX \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "object": "facility",
  "name": "Downtown Storage",
  "slug": "downtown-storage",
  "total_units": 120,
  "active_rentals": 98,
  "occupancy_rate": 81.7,
  "created_at": "2025-06-15T10:00:00+00:00",
  "updated_at": "2026-02-01T14:30:00+00:00"
}

Retrieve facility stats

GET/v1/facilities/{id}/stats

Returns dashboard-style analytics for a facility over a given period.

periodstring

Preset: today, this_month, last_month, last_3_months, last_6_months, last_12_months, year_to_date. Default: this_month

start_datestring

ISO date (YYYY-MM-DD). Overrides period when used with end_date

end_datestring

ISO date (YYYY-MM-DD). Overrides period when used with start_date

Response Attributes

units.totalinteger

Total available units

units.occupiedinteger

Currently occupied units

units.vacantinteger

Currently vacant units

occupancy_ratenumber

Percentage occupied (0–100)

tenants.totalinteger

Total customer accounts

tenants.active_rentalsinteger

Active rental subscriptions

revenue.total_collectednumber

Total paid revenue in the period

revenue.paid_invoicesinteger

Number of invoices paid in the period

revenue.overdue_amountnumber

Total currently overdue amount

revenue.overdue_countinteger

Number of currently overdue invoices

movements.move_insinteger

Move-ins during the period

movements.move_outsinteger

Move-outs during the period

Example Request
curl "https://your-domain.com/api/v1/facilities/fac_aBcDeFgHiJkLmNoPqRsTuVwX/stats?period=last_month" \
  -H "Authorization: Bearer sk_live_..."
Response
{
  "object": "facility_stats",
  "facility_id": "fac_aBcDeFgHiJkLmNoPqRsTuVwX",
  "facility_name": "Downtown Storage",
  "period": {
    "start_date": "2026-02-01",
    "end_date": "2026-02-28"
  },
  "units": {
    "total": 120,
    "occupied": 98,
    "vacant": 22
  },
  "occupancy_rate": 81.7,
  "tenants": {
    "total": 95,
    "active_rentals": 98
  },
  "revenue": {
    "total_collected": 14700.00,
    "paid_invoices": 96,
    "overdue_amount": 450.00,
    "overdue_count": 3
  },
  "movements": {
    "move_ins": 8,
    "move_outs": 5
  }
}