Introduction
This is a JSON HTTP API. It is not a RESTful API.
In contrast to REST, which is focused on the transfer of state between server and client, this API is oriented around actions that can be performed on system entities. Errors are reported via standard HTTP status codes with a structured JSON body — see Errors.
IDs
Example Entity IDs
cust_FiUtBj8JkF
lease_jOi8joH3Hu
org_Ji9JKfKkhuR
quote_IJf03jNjKuf
Entity IDs in Cubby are generally in the form of <prefix>_<alpha> where the
type of the object referred to is defined by the prefix.
Money
We represent money as an integer, representing the number of cents. There are problems both in the use of integers and in the use of floats to represent money. We believe use of integers results in more predictable and obvious behavior for users of our API, and forces anyone that sends us money to confront a possible loss of precision before sending us numbers.
Date and Time
We represent dates and times as ISO-8601 strings. Date-only fields (for example moveInDate, accruesOn, dueDate) use the form yyyy-MM-dd and carry no time component. Date-time fields fall into one of two categories:
- If the value ends in
Z, the timestamp is in UTC. For example,2024-03-01T12:00:00.000000Zis March 1, 2024 at 12:00:00 UTC. - If the value has no time zone suffix, the timestamp is in the time zone of the facility the value belongs to. For example,
2024-03-01T12:00:00on a record for a facility inAmerica/New_Yorkrepresents 12:00:00 local time at that facility (which is2024-03-01T17:00:00Zin UTC during EST).
Where search endpoints accept date or time range filters, the parameter name signals the bound semantics:
*OnOrAfter/*OnOrBefore— inclusive bounds. Used for date-only filters that describe business state on a calendar day (e.g.activeOnOrAfteron Leases Search asks for leases active on or after a given date).*After/*Before— strict (exclusive) bounds. Used for UTC timestamp filters intended as incremental-sync cursors (e.g.updatedAfterreturns records whoseupdatedAtis strictly later than the supplied timestamp, so passing the timestamp of your previous response excludes the boundary record on the next poll).
API Response Structure
Successful responses return an HTTP 200. The body is always wrapped in a small envelope:
{
"status": 200,
"data": {
/* Endpoint-specific payload. See each endpoint's documentation. */
}
}
status— always200on success. Mirrors the HTTP status.data— the endpoint-specific response payload. Omitted for endpoints that have no payload to return (the body is then just{ "status": 200 }).
Example:
POST /v1/facilities/search
{
"status": 200,
"data": {
"facilities": [
/* ... facility objects ... */
],
"organizations": [
/* ... organization objects ... */
]
}
}
Errors
Failed requests return a standard non-2xx HTTP status code (400, 401, 403, 404, 500, etc.) with the following body:
Error Response
{
"code": 404,
"errors": [
"Facility not found"
]
}
code— mirrors the HTTP status code.errors— one or more plain-english strings describing what went wrong.
Expansions
APIs strive to return comprehensive information in the target entity. Entities in the Cubby system tend to be connected
to other entities (for example a lease and a customer), and it may be desirable to retrieve both a subject entity as
well as related entities in a single HTTP request.
To accommodate this, some endpoints offer expansions, which are effectively instruction on which related entities should
be retrieved in addition to the base entity returned by the endpoint.
Expansions are not expanded in-line, but are provided as auxiliary arrays which can easily be combined by using the embedded entity IDs.
Authentication
API credentials conceptually attach to the Organization concept, and has access to all resources (managers, facilities, customers, leases) visible to the Organization.
Authentication is done via an API key, which is passed in the Authorization header.
Example via curl:
curl -X ‘POST’ https://api.cubbystorage.com/v1/organizations/search -H ‘accept: */*’ -H ‘Authorization: Bearer b73c7e4d-81f2-49e3-bbca-9a6fbd321d56’ -H "Content-Type: application/json" -d ‘{"where": {}}’
In order to obtain an API key, please contact support@cubbystorage.com.
Treat your API key like a password - because that’s what it is!
Access to PII
Access to Personally Identifiable Information (PII) is restricted to authorized users only. If your API key does not have access to PII, all PII fields will be skipped in API responses. PII fields include:
- Customer names
- Customer addresses
- Customer phone numbers
- Customer email addresses
- Customer date of birth
- Customer ID numbers
- Alternative contact names
- Alternative contact phone numbers
- Alternative contact email addresses
- Vehicle license numbers
- Vehicle states
Roles
API keys are issued with a specific role that determines which endpoints and operations are accessible. The following roles are available:
Manager
The most comprehensive role, intended for integrations that need full operational control. Grants read and write access to nearly all resources, including managing leases, customers, leads, payments, units, coverage, auctions, notes, tasks, pricing groups, and reports. Also provides read access to access codes, discounts, facilities, facility groups, ledgers, organizations, and payment methods.
Endpoints:
| Resource | Endpoints |
|---|---|
| Access Codes | search, check |
| Auctions | search, create, start-lien, cancel-lien |
| Coverage | search, enroll, unenroll, add-private-policy, remove-private-policy, download-private-policy |
| Coverage Levels | search |
| Customers | search, update |
| Discounts | search |
| Facilities | search |
| Facility Groups | search |
| Leads | search, create, update |
| Leases | search, create, checkout, cancel-lease, schedule-move-out, preview-charges, get-move-in-charges, get-upsells, make-payment, get-payment-link, enable-auto-pay, disable-auto-pay, update-alternative-contacts, get-rent-change-schedules, change-rents, cancel-rent-changes, get-compliances |
| Ledgers | search |
| Notes | search, create |
| Organizations | search |
| Payment Methods | search, create |
| Payments | search |
| Pricing Groups | search, change-rates, find-unit-for-tier |
| Reports | general-ledger/cash, general-ledger/accrual, aged-receivables, rent-roll, merchant-services-disbursements |
| Tasks | search, create |
| Units | search, set-rentability |
| Value Pricing Strategies | search |
Search
A read-only role for integrations that need to query data without making changes. Provides access to search endpoints across most resources.
Endpoints:
| Resource | Endpoints |
|---|---|
| Auctions | search |
| Coverage | search, download-private-policy |
| Coverage Levels | search |
| Customers | search |
| Discounts | search |
| Facilities | search |
| Facility Groups | search |
| Leads | search |
| Leases | search, preview-charges |
| Ledgers | search |
| Notes | search |
| Organizations | search |
| Payment Methods | search |
| Payments | search |
| Pricing Groups | search, find-unit-for-tier |
| Tasks | search |
| Units | search |
| Value Pricing Strategies | search |
Storefront
A narrow role for storefront and website integrations. Provides access to storefront-specific facility and pricing group data, along with organization info.
Endpoints:
| Resource | Endpoints |
|---|---|
| Organizations | search |
| Storefront Facilities | search |
| Storefront Pricing Groups | search |
Report
Intended for reporting and analytics integrations. Provides access to financial reports and facility data.
Endpoints:
| Resource | Endpoints |
|---|---|
| Facilities | search |
| Facility Groups | search |
| Organizations | search |
| Reports | general-ledger/cash, general-ledger/accrual, aged-receivables, rent-roll, merchant-services-disbursements |
Coverages
Designed for insurance and coverage provider integrations. Grants full coverage management along with read access to the related resources needed to look up customers, leases, and units.
Endpoints:
| Resource | Endpoints |
|---|---|
| Coverage | search, enroll, unenroll, add-private-policy, remove-private-policy, download-private-policy |
| Coverage Levels | search |
| Customers | search |
| Facilities | search |
| Facility Groups | search |
| Leases | search, preview-charges |
| Ledgers | search |
| Organizations | search |
| Pricing Groups | search, find-unit-for-tier |
| Units | search |
| Value Pricing Strategies | search |
Access Codes
A minimal role for gate access integrations. Provides the ability to look up and verify access codes.
Endpoints:
| Resource | Endpoints |
|---|---|
| Access Codes | search, check |
Communication
Allows sending SMS and email messages on behalf of the organization.
Endpoints:
| Resource | Endpoints |
|---|---|
| Messages | sms/send, email/send |
Locks
For smart lock integrations. Grants the ability to manage locks — register, attach, disable, return, and transfer.
Endpoints:
| Resource | Endpoints |
|---|---|
| Locks | search, register, disable, attach, return, transfer |
Changelog
August 2026
- Rent Roll Report:
lastRentChangeDatefield — Entries inPOST /v1/reports/rent-rollnow include alastRentChangeDatefield, the date of the tenant's last completed rent change (omitted if the rent has never changed). - Rent Roll Report:
effectiveRatefield — Entries inPOST /v1/reports/rent-rollnow include aneffectiveRatefield, the net rent for the unit in cents (rent less discounts and waived rent) charged for the current billing period. - Managers Search:
phonefilter normalised to E.164 — Thephonefilter onPOST /v1/managers/searchis now normalised to E.164 and matched exactly, so a full number in any common spelling (555-555-5555,(555) 555-5555,+15555555555) matches the same manager. A value that is not a full phone number is now rejected with a400, and partial-number search is not supported on this filter. (customers/searchis unchanged: itsphoneremains a partial match.)
July 2026
- Rent Roll Report:
creditfield — Entries inPOST /v1/reports/rent-rollnow include acreditfield, the tenant's available credit balance for the unit in cents. - Checkout: save card & enable AutoPay —
POST /v1/leases/checkoutaccepts an optionalenableAutoPayflag. When set, a successful payment also saves the card supplied inpaymentto the customer as a reusable payment method and enrols the new lease in AutoPay using that card; when omitted, the card is charged but not saved. The response gainspaymentMethodId(the ID of the saved method,nullwhen AutoPay was not requested or the save did not succeed) and anautoPayEnabledboolean — so integrators can confirm each outcome independently of the payment result;paymentFailureInforemains reserved for payment failures. - Pricing Groups: value-pricing tiers —
POST /v1/pricing-groups/searchnow returnsvaluePricingStatus(NOT_CONFIGURED,REVIEW_REQUIRED, orAPPROVED) on every pricing group, plus anavailableTiersarray on eachAPPROVEDgroup — the subset ofLOWEST,MEDIUM,HIGHESTcurrently offered, based on how many units are available. New endpointPOST /v1/pricing-groups/find-unit-for-tierresolves a selected tier to the concrete unit a renter would be assigned, using the same ranking the storefront applies. - Leads Update — New endpoint
POST /v1/leads/update. Modifies an existing lead's unit, pricing group, coverage, discounts, rate, status, source, and target move-in date: omitted fields are left unchanged and an explicitnullclears the value. Validation matches the staff UI (valid unit/coverage for the facility, discounts available for the pricing group,customRaterequired when settingrateTypetoCUSTOM_RATE). To stay predictable, update does not perform reservation transitions. - Leads Search:
originand lifecycle timestamps —POST /v1/leads/searchnow returns anoriginfield describing how the lead was created (MANAGER,API,AI_VOICE_AGENT,CONTACT_FORM,WAITLIST_FORM,RESERVATION_FORM,WEBSITE_CHECKOUT,RESERVED_CHECKOUT,ABANDONED_CHECKOUT, orFAILED_CHECKOUT), plus four lifecycle fields:reservedAt,convertedAt, andunqualifiedAt(ISO-8601 UTC timestamps,nulluntil the lead reaches that state) andleaseMoveInDate(YYYY-MM-DD, the start date of the lease created from the lead, ornull). - Leads: coverage / discounts / custom rate —
POST /v1/leads/createnow acceptscoverageLevelId,discounts,rateType, andcustomRate(alongside the existingunitId), andPOST /v1/leads/searchreturnscoverageType,coverageLevelId,discounts,rateType, andcustomRateon every lead — including assignments staff set in the Cubby app. Thediscountsarray is now populated on lead objects wherever they appear — including theleadsexpansion ofPOST /v1/customers/search(previously omitted there). - Communication preferences —
POST /v1/customers/update,POST /v1/leads/create,POST /v1/leases/create, andPOST /v1/leases/checkoutnow accept an optionalcommunicationPreferencesobject with per-channel marketing opt-in flags (smsMarketing,emailMarketing). On the create/checkout endpoints it lives inside thecustomerobject. Each flag is optional —trueopts the channel in to promotions,falserestricts it to transactional messages, and an omitted flag leaves that channel unchanged.
June 2026
- Facility Groups Search — New endpoint
POST /v1/facility-groups/search, searchable byfacilityGroupIdororganizationId. Each group always carries afacilityIdsarray; afacilitiesexpansion adds a top-level array of the full member facility objects.POST /v1/facilities/searchnow also accepts afacilityGroupIdfilter, always returns afacilityGroupIdsarray on each facility, and supports afacilityGroupsexpansion that adds a top-level array of the related facility groups. - Discounts:
pricingGroupsfield — Discount objects inPOST /v1/discounts/searchnow include apricingGroupsarray listing every pricing group the discount applies to, withpricingGroupId,name, andvisibility(ALLorCUBBY_ONLY). Visibility is configured per discount-and-pricing-group pairing. - Discounts:
applicationPercentagefield — Discount objects inPOST /v1/discounts/search(and lease discounts) now includeapplicationPercentageforPERCENT_DEDUCTEDdiscounts, expressing the percentage directly (e.g.10for 10%). For backward compatibility these discounts continue to populateapplicationAmountwith the percentage scaled by 100 (10% →1000). ThatapplicationAmountvalue for percentage discounts is deprecated and scheduled for removal in mid-July 2026 - Get Upsells — New endpoint
POST /v1/leases/get-upsells. Returns the optional upsell (upgrade) recurring fees available for a unit. Opt into an upsell at move-in by passing itsfeeIdin theupsellFeeIdsarray ofPOST /v1/leases/get-move-in-charges,POST /v1/leases/create, orPOST /v1/leases/checkout. - Facilities Search:
schedulesexpansion —POST /v1/facilities/searchnow supports aschedulesexpansion. When requested, each facility object includes aschedulesarray describing the facility's configured schedules (office hours, phone support, etc.). - Facilities Search:
timeZonefield — The facility object inPOST /v1/facilities/searchnow includes atimeZonefield containing the facility's IANA time zone identifier (e.g.America/New_York). - Units Search:
legacyIdfield — Unit objects inPOST /v1/units/searchnow include alegacyIdfield containing the original unit ID from the source management software (e.g. SiteLink), preserved during import so partners can re-map their unit references after a migration.nullfor units not created via import.
May 2026
- Merchant Services Disbursements Report — New endpoint
POST /v1/reports/merchant-services-disbursementsfor retrieving batch settlement and transaction details from configured payment providers. - Value Pricing Strategies Search — New endpoint
POST /v1/value-pricing-strategies/search.POST /v1/pricing-groups/searchnow also returnsvaluePricingStrategyIdon each pricing group with a strategy assigned, plus a top-levelvaluePricingStrategiesarray when thevaluePricingStrategiesexpansion is requested. - Leases, Leads, Customers Search:
createdAt/updatedAttimestamps —createdAtandupdatedAtUTC timestamps are now included on objects returned byPOST /v1/leases/search,POST /v1/leads/search, andPOST /v1/customers/search. - Search endpoints:
updatedAfter/updatedBeforefilters — Strict (exclusive) UTC timestamp filtersupdatedAfterandupdatedBeforeadded to/v1/leases/search,/v1/leads/search, and/v1/customers/search. Designed as incremental-sync cursors: passing theupdatedAtfrom your previous response asupdatedAfteron the next poll excludes the boundary record. - Leases Search:
activeOnOrAfter/activeOnOrBeforefilter fix — These inclusive date filters now apply consistently across all code paths in/v1/leases/search. - Aged Receivables Report: optional
throughDateparameter —POST /v1/reports/aged-receivablesnow accepts an optionalthroughDate. When supplied, aging buckets are computed as of the end of that date, enabling historical snapshots. Defaults to the facility's current date. - Get Documents Link — New endpoint
POST /v1/leases/get-documents-link. Returns adocumentsLinkURL pointing to the tenant portal page where the tenant can view, manage, and sign lease documents. - Documentation: roles and permissions — New section documenting the
Manager,Search, andStorefrontAPI key roles with per-resource access tables.
April 2026
- Checkout — New endpoint
POST /v1/leases/checkout. Creates a lease and collects the first payment atomically. Accepts allCreate Leasefields plus a requiredpaymentobject (amount, billing address,methodType, and gateway token). On payment decline the lease is rolled back; the response includespaymentSuccess,paymentTransactionId, andpaymentFailureInfo. - Auctions:
leaseConfigurationIdfield —leaseConfigurationIdadded to auction-create requests and auction-search responses, linking an auction to the lease configuration (agreement template) assigned to the pricing group.
March 2026
- Leases Search:
scheduledMoveOutfield — Lease objects in/v1/leases/searchnow include ascheduledMoveOutobject when a move-out is scheduled:moveOutDate,noticeGivenDate,moveOutReason,customReason, andmoveOutTime. - Leads Create: facility-level token support —
POST /v1/leads/createnow accepts afacilityIdin place oforganizationIdwhen using a facility-scoped API token.
February 2026
- AutoPay Enable / Disable — New endpoints
POST /v1/leases/enable-auto-payandPOST /v1/leases/disable-auto-pay.enable-auto-payrequiresleaseIdandpaymentMethodId;disable-auto-payrequiresleaseIdonly. Lease objects in/v1/leases/searchnow includeautoPayPaymentMethodId. - Leases Search:
coverageChangefield — Lease objects now include acoverageChangeobject showing the next scheduled coverage change:coverageType,startDate,coverageLevelId,premiumAmount, andcoverageAmount. - Lease Compliance — New endpoints
POST /v1/leases/get-compliancesand acomplianceexpansion on/v1/leases/search. Returns per-lease compliance status for each required document type (LEASE_AGREEMENT,COVERAGE,IDENTITY,VEHICLE) with statusesNOT_REQUIRED,INCOMPLETE,PENDING_APPROVAL,SIGNATURE_NEEDED,REJECTED, orAPPROVED. - Accrual General Ledger Report — New endpoint
POST /v1/reports/general-ledger/accrual. Returns journal entry line items withdebit/creditamounts,account,taxCategory,taxExempt,explanation, and GL mapping fields. RequiresfacilityId,startDate, andreportRelativeDuration. - Ledger Search:
paymentTimefield —paymentTimeUTC timestamp added to charge entries in/v1/ledgers/search, indicating when the charge was fully paid. - Pricing Groups Change Rates:
strikethroughRatefield —strikethroughRateadded as an optional property onPOST /v1/pricing-groups/change-rates. Setting it tonullremoves the strikethrough price; it only displays on the storefront when greater than the web rate. - Facilities Search: additional fields —
internalName,organizationId,longitude,latitude, andpaymentServiceProvider(STRIPEorPAYABLI) added to facility objects in/v1/facilities/search. - Units Search:
walkthroughOrderfield —walkthroughOrderinteger added to unit objects in/v1/units/search.
January 2026
- Leads Search — New endpoint
POST /v1/leads/search. Filters byorganizationId,facilityId,customerId,pricingGroupId,unitId, orleadId. Supportsfacility,unit,pricingGroup, andcustomerexpansions. - Rent Roll Report — New endpoint
POST /v1/reports/rent-roll. Returns a per-unit snapshot includingmonthlyRentalAmount,rentVarianceAmount,totalDue,deposit,prepaid,moveInDate,paidThroughDate,autoPayEnabled, overlock status, scheduled rent-change fields, and customer contact details. RequiresfacilityIdsandthroughDate. - Payment Methods Create — New endpoint
POST /v1/payment-methods/create. Accepts a gatewaytokenandmethodType(CREDIT_CARD,ACH, orACSS) with method-specific fields (card brand, expiration, last four, holder; ACH/ACSS account type, holder, last four). - Units Set Rentability — New endpoint
POST /v1/units/set-rentability. Sets a unit'srentableboolean; whenfalse, requiresunrentableReason(REPAIRS_REQUIRED,CLEANING_REQUIRED,UNDER_RENOVATION,USED_BY_FACILITY,OTHER) and an optionalunrentableReasonNote.
December 2025
- Aged Receivables Report — New endpoint
POST /v1/reports/aged-receivables. Returns per-lease aging buckets (RANGE_0_30,RANGE_30_60,RANGE_60_90,RANGE_90_120,RANGE_120_PLUS) for one or more facilities. - Ledger Search:
waiveflag —waiveboolean added to charge entries in/v1/ledgers/search, indicating whether the charge has been waived. - Pricing Groups Change Rates — New endpoint
POST /v1/pricing-groups/change-rates. Bulk-updatesstandardRateand/orwebRatefor one or more pricing groups bypricingGroupId. - Customers Search:
companyNamefield —companyNameadded to customer objects returned by/v1/customers/searchand other endpoints that embed customer data.
November 2025
- Change Rents — New endpoints for scheduling and applying rent changes on leases.
- Notes Search / Create — New endpoints
POST /v1/notes/searchandPOST /v1/notes/create. - General Ledger Cash Report: GL mapping fields —
mappedGlAccountandmappedGlAccountNumberadded to line items inPOST /v1/reports/general-ledger/cashwhen a GL mapping is configured for the facility.
October 2025
- Leases Search:
pricingGroupexpansion — Theexpansionsarray on/v1/leases/searchnow supportspricingGroup, returning the pricing group object alongside each lease.
September 2025
- Lock Transfer — New endpoint
POST /v1/locks/transfer. Transfers a lock to a different facility within the same organization. The lock must not be currently attached to a unit.
December 2024
- Pricing Groups Search — New endpoint
POST /v1/pricing-groups/search. Returns storefront-visible pricing groups byfacilityIdorpricingGroupId, including standard rate, web rate,strikethroughRate, dimensions, features, and an optionaldiscountsexpansion. - Payments Search — New endpoint
POST /v1/payments/search. Filters byfacilityIdorcustomerId, with optionalpaymentDateOnOrAfter/paymentDateOnOrBeforedate range filters.
Operator API
Access Codes
Access Codes Search
POST /v1/access-codes/search
Request Body — access-codes/search
{
"where": {
"facilityId": "fac_<ID>",
"customerId": "cust_<ID>"
}
}
Response Body — access-codes/search
{
"status": 200,
"data": {
"accessCodes": [
{
"code": "1575",
"enabled": true,
"customerId": "cust_K2kybwxRz9L"
},
{/* ... */}
]
}
}
Search for access codes by facility or customer
Required Properties
facilityId- the ID of the facility to search for access codes
Check Access Code
POST /v1/access-codes/check
Request Body — access-codes/check
{
"facilityId": "fac_<ID>",
"code": "1575"
}
Response Body — access-codes/check
{
"status": 200,
"data": {
"accessAllowed": true,
"message": "Access allowed"
}
}
Check if an access code is valid for a facility
Required Properties
facilityId- the ID of the facility to check the access code againstcode- the access code to check
Response Parameters
accessAllowed- a boolean indicating if the access code is validmessage- a message indicating the result of the check; examples include"Access allowed","Code not found", and"Code disabled"
Locks
Lock Register
POST /v1/locks/register
Request Body — locks/register
{
"serial": "M9U2FK",
"combo": "2934",
"location": "fac|org_<ID>",
"actor": "user_<ID>",
}
Response Body — locks/register
{
"status": 200,
"data": {
"id": "lock_<ID>"
}
}
Adds a new lock to the system. The lock is initially in an "available" state. Available locks can be associated with a location until they are attached to a unit.
Required Properties
serial- the serial number of the lockcombo- the current combination for unlocking the locklocation- thefacilityororganizationwhere the lock is physically present
Error Conditions
- It is an error to add a lock whose serial already exists in the system
Response Parameters
| Parameter | Description |
|---|---|
| id | The ID of the newly registered lock |
Lock Search
POST /v1/locks/search
Request Body — locks/search
{
"where": {
"organizationId": "org_<ID>"
}
}
Response Body — locks/search
{
"status": 200,
"data": {
"locks": [
{
"id": "lock_<ID>",
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"serial": "M9U2FK",
"combo": "2934",
"status": "AVAILABLE | OPERATOR_USE | TENANT_USE | DISABLED",
"attachedTo": "unit_<ID>",
"disabledReason": "DAMAGED | MISSING"
},
{/* ... */}
]
}
}
Search for locks by organization
Required Properties
organizationId- the ID of the organization to search for locks
Response Parameters
| Parameter | Description |
|---|---|
| id | The ID of the lock |
| facilityId | The facility where the lock is physically present |
| organizationId | The organization where the lock is physically present |
| serial | The serial number of the lock |
| combo | The current combination for unlocking the lock |
| status | The current status of the lock. |
| attachedTo | The unit to which the lock is attached (only when status is either OPERATOR_USE or TENANT_USE) |
| disabledReason | The reason the lock is disabled (only when status is DISABLED) |
Lock Disable
POST /v1/locks/disable
Request Body — locks/disable
{
"lockId": "lock_<ID>",
"reason": "DAMAGED | MISSING",
"actor": "user_<ID>"
}
Marks the lock as disabled, detaching it from any units it may be attached to.
Required Properties
lockId- the ID of the lock which will be disabledreason- the reason for disabling the lock, which can beDAMAGEDorMISSING
Optional Properties
actor- the user who performed this action
Lock Attach
POST /v1/locks/attach
Request Body — locks/attach
{
"lockId": "lock_<ID>",
"attachTo": "space_<ID>",
"lockUse": "TENANT_USE | OPERATOR_USE",
"actor": "user_<ID>"
}
Attaches a lock to a unit either by renting it to a tenant or by restricting access to the unit.
Required Properties
lockId- the ID of the lockattachTo- the ID of the space the lock will be attached tolockUse-TENANT_USElock use means that the lock has been rented-to or loaned-to a tenant; the code will be immediately accessible to the tenant, and it is even possible that the tenant will change the code.OPERATOR_USEmeans the purpose of the lock is to restrict access to the unit
Optional Properties
actor- the user who performed this action
Error Conditions
- Cannot attach a lock to a space which already has a different lock attached to it
Lock Return
POST /v1/locks/return
Request Body — locks/return
{
"lockId": "lock_<ID>",
"actor": "user_<ID>"
}
Puts the lock back into inventory, detaching it from any unit it may be currently attached to and marking it available for re-use.
Required Properties
lockId- the ID of the lock
Optional Properties
actor- the user who performed this action
Lock Transfer
POST /v1/locks/transfer
Request Body — locks/transfer
{
"lockId": "lock_<ID>",
"facilityId": "fac_<ID>"
}
Transfers the lock to a different facility, which must belong to the same organization as the lock's current facility. The lock must not be attached to a unit.
Required Properties
lockId- the ID of the lockfacilityId- the ID of the facility to which the lock will be transferred
Organizations
Organizations Search
POST /v1/organizations/search
Request Body — organizations/search
{
"where": {
"organizationId": "org_4a2da7d271a"
}
}
Response Body — organizations/search
{
"status": 200,
"data": {
"organizations": [
{
"organizationId": "org_4a2da7d271a",
"name": "Anisha Estates"
},
{/* ... */}
]
}
}
Returns metadata for co-managed organization(s)
Optional Properties
organizationId- limits results to organizations with a specific ID, otherwise all co-managed organizations are returned
Managers
Managers Search
POST /v1/managers/search
Request Body — managers/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"phone": "555-555-5555",
"email": "manager@example.com",
"name": "Jane",
"includePermissions": true
}
}
Response Body — managers/search
{
"status": 200,
"data": {
"managers": [
{
"managerId": "user_4a2da7d271a",
"name": "Jane Smith",
"email": "manager@example.com",
"phone": "+15555555555",
"organizationId": "org_4a2da7d271a",
"organizationPermissions": {
"organizationId": "org_4a2da7d271a",
"name": "Anisha Estates",
"permissions": {
"read": ["Task"],
"manage": ["Task", "Note"]
}
},
"facilitiesPermissions": [
{
"facilityId": "fac_C7bSZyPT6fp",
"name": "315 Anisha Estates",
"permissions": {
"read": ["Task"],
"manage": ["Task", "Note"]
}
},
{/* ... */}
]
},
{/* ... */}
]
}
}
Search for managers by facility, organization, or contact information
Required Properties
facilityId- limits results to managers at a specific facility- or
organizationId- limits results to managers in a specific organization
Optional Properties
phone- filters managers by phone number. Normalised to E.164 and matched exactly, so a full number in any common spelling (555-555-5555,(555) 555-5555,+15555555555) matches the same manager, and a value that is not a full phone number is rejected with a400. Partial-number search is not supported on this filter. (customers/searchis unchanged: itsphoneremains a partial match.)email- filters managers by email addressname- filters managers by nameincludePermissions- a boolean indicating whether to include permission details in the response (defaults totrue)
Facilities
Facilities Search
POST /v1/facilities/search
Request Body — facilities/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"facilityGroupId": "fg_4a2da7d271a"
},
"expansions": [
"organization",
"schedules",
"facilityGroups"
]
}
Response Body — facilities/search
{
"status": 200,
"data": {
"facilities": [
{
"facilityId": "fac_C7bSZyPT6fp",
"name": "315 Anisha Estates",
"internalName": "Anisha",
"contact": {
"address": "315 Anisha Estates",
"address2": "",
"city": "Thompsonview",
"state": "Alaska",
"country": "USA",
"zip": "98748",
"email": "",
"phone": ""
},
"organizationId": "org_4a2da7d271a",
"longitude": "-122.419418",
"latitude": "37.774929",
"timeZone": "America/New_York",
"paymentServiceProvider": "STRIPE | PAYABLI",
"schedules": [
{
"name": "Office Hours",
"schedule": [
null,
{"from": "09:00:00", "to": "17:00:00"},
{"from": "09:00:00", "to": "17:00:00"},
{"from": "09:00:00", "to": "17:00:00"},
{"from": "09:00:00", "to": "17:00:00"},
{"from": "09:00:00", "to": "17:00:00"},
null
],
"category": "SYSTEM | CUSTOM",
"systemTypes": ["PHONE_SUPPORT", "OFFICE_HOURS"]
},
{/* ... */}
],
"facilityGroupIds": ["fg_4a2da7d271a"]
},
{/* ... */}
],
"organizations": [
{
"organizationId": "org_4a2da7d271a",
"name": "Anisha Estates"
},
{/* ... */}
],
"facilityGroups": [
{
"facilityGroupId": "fg_4a2da7d271a",
"name": "Main Street Campus",
"organizationId": "org_4a2da7d271a"
},
{/* ... */}
]
}
}
Returns metadata for all co-managed facilities
Each facility object includes a paymentServiceProvider field indicating which payment gateway
the facility is configured to use — either STRIPE or PAYABLI. Use this to determine which
token-generation flow to follow when collecting payment details (see
Generating a Payment Token).
Each facility object always includes a facilityGroupIds array — the ext ids of the facility groups it belongs to
(empty when the facility is in no group). This is the lightweight membership signal and requires no expansion.
Required Properties
Exactly one of the following must be provided:
facilityId- limits results to a specific facilityorganizationId- limits results to facilities belonging to a specific organizationfacilityGroupId- limits results to the facilities that are members of a specific facility group
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint areorganization,schedulesandfacilityGroups
When the facilityGroups expansion is requested, the response additionally includes a top-level facilityGroups
array (sibling to facilities) containing the de-duplicated set of facility groups that the returned facilities
belong to. Each entry has facilityGroupId, name, and organizationId. Match them to facilities via each
facility's facilityGroupIds. Without the expansion, only the per-facility facilityGroupIds (above) is returned.
See Facility Groups for the full facility-group resource.
When the schedules expansion is requested, each facility object includes a schedules array describing the
facility's configured schedules (office hours, phone support, etc.). Each schedule has the following fields:
name- the schedule's display nameschedule- the weekly schedule definition: a JSON array of exactly 7 elements, one per day of the week ordered Sunday first (index0= Sunday,6= Saturday). Each element is eithernull(closed that day) or an object{"from": "HH:MM:SS", "to": "HH:MM:SS"}giving the open and close times in the facility's local time zone. The example above is closed on Sunday and Saturday and open 09:00–17:00 Monday through Friday.category-SYSTEMfor Cubby-managed schedules orCUSTOMfor operator-defined schedulessystemTypes- forSYSTEMschedules, the system functions the schedule drives; zero or more ofPHONE_SUPPORT,OFFICE_HOURS
Facility Groups
Facility groups are named, organization-level collections of facilities. A facility can belong to multiple groups at once. They are commonly used to present several nearby facilities as a single location to customers.
Facility Groups Search
POST /v1/facility-groups/search
Request Body
{
"where": {
"facilityGroupId": "fg_4a2da7d271a",
"organizationId": "org_4a2da7d271a"
},
"expansions": [
"facilities"
]
}
Response Body
{
"status": 200,
"data": {
"facilityGroups": [
{
"facilityGroupId": "fg_4a2da7d271a",
"name": "Main Street Campus",
"organizationId": "org_4a2da7d271a",
"facilityIds": ["fac_C7bSZyPT6fp", "fac_D8cTZyQU7gq"]
},
{/* ... */}
],
"facilities": [
{
"facilityId": "fac_C7bSZyPT6fp",
"name": "315 Anisha Estates",
"organizationId": "org_4a2da7d271a",
"/* ... same shape as Facilities Search ... */": ""
},
{/* ... */}
]
}
}
Each facility group always includes a facilityIds array — the ext ids of its member facilities (empty when the
group has none). This requires no expansion.
Required Properties
Exactly one of the following must be provided:
facilityGroupId- returns the single matching facility grouporganizationId- returns all facility groups belonging to a specific organization
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; the only supported value for this endpoint isfacilities
When the facilities expansion is requested, the response additionally includes a top-level facilities array
(sibling to facilityGroups) containing the de-duplicated full facility objects (same shape as
Facilities Search) for all member facilities of the returned groups. Match them to groups via
each group's facilityIds. Without the expansion, only the per-group facilityIds is returned.
Units
Units Search
POST /v1/units/search
Request Body — units/search
{
"where": {
"unitId": "unit_GfNkzV4itfk",
"pricingGroupId": "pg_4a2da7d271a",
"facilityId": "fac_C7bSZyPT6fp"
},
"expansions": [ ... ]
}
Response Body — units/search
{
"status": 200,
"data": {
"units": [
{
"unitId": "unit_GfNkzV4itfk",
"name": "M001",
"width": 20,
"depth": 30,
"height": null,
"area": 600,
"volume": null,
"overlocked": false,
"rentability": {
"rentable": true,
"unrentableReason": "ACTIVE_LEASE | REPAIRS_REQUIRED | CLEANING_REQUIRED | UNDER_RENOVATION | USED_BY_FACILITY | OTHER",
"unrentableReasonNote": "Note why the unit is unavailable"
},
"insurable": true,
"floorName": "1",
"facilityId": "fac_C7bSZyPT6fp",
"leaseId": "lease_V4w64pjUwVK",
"pricingGroupId": "pg_4a2da7d271a",
"accessInstructions": "Your unit is located on the first floor, down the hall to the left.",
"walkthroughOrder": 1,
"legacyId": "19455"
},
{/* ... */}
]
}
}
Returns metadata for spaces at co-managed facilities
Required Properties
unitId- limits results to a specific unit- or
facilityId- limits results to spaces in a particular facility- or
pricingGroupId- limits results to spaces in a particular pricing group
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; supported for this- endpoint are
facility,leaseandpricingGroup
Unit Set Rentability
POST /v1/units/set-rentability
Request Body — units/set-rentability
{
"unitId": "unit_GfNkzV4itfk",
"rentable": false,
"unrentableReason": "REPAIRS_REQUIRED | CLEANING_REQUIRED | UNDER_RENOVATION | USED_BY_FACILITY | OTHER",
"unrentableReasonNote": "Note why the unit is unavailable"
}
Sets the rentability of a unit.
Required Properties
unitId- the ID of the unit to updaterentable- boolean indicating if the unit is rentable or not- if
rentableisfalse:unrentableReason- the reason why the unit is not rentable. Can be one of the following:REPAIRS_REQUIREDCLEANING_REQUIREDUNDER_RENOVATIONUSED_BY_FACILITYOTHER
unrentableReasonNote- a note explaining the reason why the unit is not rentable. This field is optional.
- if
rentableistruethese two fields are ignored
Pricing Groups
- Pricing Group Search
- Pricing Groups Change Rates
- Pricing Groups Find Unit For Tier
- Discounts Search
- Value Pricing Strategies Search
Pricing Group Search
POST /v1/pricing-groups/search
Request Body — pricing-groups/search
{
"where": {
"facilityId": "fac_4a2da7d271a",
"pricingGroupId": "pg_4a2da7d271a"
},
"expansions": [ ... ]
}
Response Body — pricing-groups/search
{
"status": 200,
"data": {
"pricingGroups": [
{
"pricingGroupId": "pg_4a2da7d271a",
"facilityId": "fac_C7bSZyPT6fp",
"leaseConfigurationId": "lc_4a2da7d271a",
"name": "Standard",
"width": 20,
"depth": 30,
"height": null,
"area": 600,
"vehicleStorage": false,
"parking": false,
"standardRate": 22000,
"walkInRate": 20000,
"webRate": 18000,
"strikethroughRate": 16000,
"features": [
"Climate controlled",
"Ground floor",
"Drive-up"
],
"discounts": [
"discount_JgNkzV4itfk",
"discount_ji43jNjKuf"
],
"availableDiscounts": [
"discount_JgNkzV4itfk"
],
"availableUnits": 14,
"valuePricingStrategyId": "vps_4a2da7d271a",
"valuePricingStatus": "APPROVED",
"availableTiers": [ "LOWEST", "MEDIUM", "HIGHEST" ]
},
{/* ... */}
]
}
}
Search for pricing groups by facilityId or pricingGroupId.
Required Properties
facilityId- limits results to pricing groups in a particular facility- or
pricingGroupId- limits results to a specific pricing group - or
organizationId- limits results to an organization
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint arediscounts,facilities,valuePricingStrategies
Response Parameters
discounts- every active discount program assigned to the pricing groupavailableDiscounts- the subset ofdiscountsthat can currently be applied, after filtering each program's occupancy-percentage and available-units restrictions against the pricing group's current unit countsarea- the floor area of units in the pricing group, in square feet (width×depth)availableUnits- the number of units in the pricing group currently available for rentvaluePricingStatus- the unit-ranking state of the pricing group's value-pricing configuration:NOT_CONFIGURED(no strategy assigned),REVIEW_REQUIRED(a strategy is assigned but one or more active units are unranked), orAPPROVED(a strategy is assigned and every active unit is ranked). Tier pricing is live only whenAPPROVED.availableTiers- the value-pricing tiers currently offered for this pricing group, a subset ofLOWEST,MEDIUM,HIGHESTthat depends on how many units are available (LOWESTneeds at least one available unit,MEDIUMat least two,HIGHESTat least three). Only present whenvaluePricingStatusisAPPROVED; omitted otherwise. Resolve a chosen tier to a concrete unit withfind-unit-for-tier.
Pricing Groups Change Rates
POST /v1/pricing-groups/change-rates
Request Body — pricing-groups/change-rates
{
"pricingGroups": [
{
"pricingGroupId": "pg_4a2da7d271a",
"standardRate": 23000,
"webRate": 21000,
"strikethroughRate": 25000
}
]
}
Changes rates for pricing groups. Only the rates that are to be updated need to be included in the request.
Required Properties
pricingGroupId- the ID of the pricing group to update
Optional Properties
standardRate- the new standard rate for the pricing group. Cannot benullif provided.webRate- the new web rate for the pricing group. Ifnull, the web rate defaults to the configured pricing strategy, or the pricing group's standard rate.strikethroughRate- the strikethrough price to display on the storefront. Ifnull, the strikethrough price is disabled. Even when enabled, the strikethrough price won't display on your storefront when it's less than or equal to the web rate.
Pricing Groups Find Unit For Tier
POST /v1/pricing-groups/find-unit-for-tier
Request Body — pricing-groups/find-unit-for-tier
{
"pricingGroupId": "pg_4a2da7d271a",
"tier": "LOWEST | MEDIUM | HIGHEST"
}
Response Body — pricing-groups/find-unit-for-tier
{
"status": 200,
"data": {
"unitId": "unit_4a2da7d271a"
}
}
Resolves a value-pricing tier to the concrete unit a renter would be assigned, using the same ranking the storefront
applies: HIGHEST maps to the best-ranked available unit, LOWEST to the lowest-ranked, and MEDIUM to the unit
closest to the middle of the ranking. Call Pricing Group Search first and offer only the
tiers listed in availableTiers.
Required Properties
pricingGroupId- the pricing group to resolve the unit withintier- the selected value-pricing tier, one ofLOWEST,MEDIUM,HIGHEST
Response Parameters
unitId- the ID of the resolved unit. Omitted when the pricing group has no unit available to rent, or when the requestedtieris not currently offered for the group (i.e. not present in the group'savailableTiers).
Discounts Search
POST /v1/discounts/search
Request Body — discounts/search
{
"where": {
"pricingGroupId": "pg_4a2da7d271a",
"discountId": "discount_JgNkzV4itfk",
"organizationId": "org_<ID>"
}
}
Response Body — discounts/search
{
"status": 200,
"data": {
"discounts": [
{
"discountId": "discount_JgNkzV4itfk",
"name": "First Month Free",
"type": "PERPETUAL | PERIODIC | PAID_UPFRONT | ONE_TIME",
"status": "PUBLISHED | ARCHIVED",
"startAfterMonths": 1,
"discountedMonths": 1
// Upfront discount fields
"upfrontPaidMonths": 1,
"upfrontFreeMonths": 1,
// Periodic / perpetual discount fields.
"applicationMethod": "PERCENT_DEDUCTED | AMOUNT_DEDUCTED | AMOUNT_FIXED",
"applicationAmount": 1000, // AMOUNT_DEDUCTED / AMOUNT_FIXED: value in cents. PERCENT_DEDUCTED: percentage x100 (10% -> 1000), DEPRECATED (see Changelog)
"applicationPercentage": 10, // PERCENT_DEDUCTED only, a percentage (0-100)
// every pricing group the discount applies to, with its channel visibility
"pricingGroups": [
{
"pricingGroupId": "pg_4a2da7d271a",
"name": "Standard",
"visibility": "ALL | CUBBY_ONLY"
}
]
},
{/* ... */}
]
}
}
Search for discounts by pricing group or discount id
A discount expresses its value through applicationAmount and/or applicationPercentage, depending on applicationMethod:
AMOUNT_DEDUCTED(a flat sum off the rent) andAMOUNT_FIXED(a fixed replacement rent) carryapplicationAmount, in cents.PERCENT_DEDUCTED(a percentage off the rent) carriesapplicationPercentage, a percentage between 0 and 100. For backward compatibility it currently also populatesapplicationAmountwith the percentage scaled by 100 (10% →1000). ThatapplicationAmountvalue is deprecated and scheduled for removal in mid-July 2026 — migrate toapplicationPercentage.
Each discount also carries a pricingGroups array listing every pricing group it applies to. Each entry has the pricing group's pricingGroupId and name, plus the visibility (ALL or CUBBY_ONLY) configured for that discount in that pricing group — visibility is per discount-and-pricing-group pairing, so the same pricing group may show a different value on a different discount.
Required Properties
pricingGroupId- limits results to discounts in a particular pricing group
Value Pricing Strategies Search
POST /v1/value-pricing-strategies/search
Request Body — value-pricing-strategies/search
{
"where": {
"valuePricingStrategyId": "vps_4a2da7d271a"
}
}
Response Body — value-pricing-strategies/search
{
"status": 200,
"data": {
"valuePricingStrategies": [
{
"valuePricingStrategyId": "vps_4a2da7d271a",
"name": "Unit Type Value Pricing",
"tiers": [
{
"tier": "LOWEST",
"name": "Standard",
"benefits": [
"Furthest from the entrance",
"Best when you rarely visit your unit"
]
},
{
"tier": "MEDIUM",
"name": "Premium",
"increaseType": "AMOUNT",
"increaseAmount": 400,
"benefits": [
"Convenient Location",
"Save money and steps"
]
},
{
"tier": "HIGHEST",
"name": "VIP",
"increaseType": "PERCENTAGE",
"increasePercentage": 15.00,
"benefits": [
"Best Location",
"Closest to entrance, elevator, or stairs"
]
}
]
}
]
}
}
Search for value-pricing strategies by strategy id, facility id, or organization id. Exactly one where field must be specified.
A value-pricing strategy defines tier increases (good / better / best) relative to a base rate, but does not itself store one. Per-tier effective rates are computed client-side from each pricing group's webRate and the tier's increaseType plus its type-specific amount:
AMOUNT: effective rate =webRate + increaseAmount(where both are in cents)PERCENTAGE: effective rate =webRate * (1 + increasePercentage / 100)
Each non-LOWEST tier carries exactly one of increaseAmount or increasePercentage, matching its increaseType. The LOWEST tier never carries increaseType, increaseAmount, or increasePercentage — by definition it has no increase.
Required Properties
valuePricingStrategyId— returns the strategy with this id- or
facilityId— returns the distinct set of strategies assigned to any pricing group in the facility - or
organizationId— returns all strategies belonging to the organization (regardless of assignment)
Customers
Customers Search
POST /v1/customers/search
Request Body — customers/search
{
"where": {
"customerId": "cust_BqaN6zApXCH",
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"name": "Bebe Flatley",
"phone": "+15943590263",
"email": "bebe.flatley@example.com",
"lease": "ACTIVE | ANY",
"lead": "ACTIVE | ANY"
},
"expansions": [
"leads"
]
}
Response Body — customers/search
{
"status": 200,
"data": {
"customers": [
{
"customerId": "cust_BqaN6zApXCH",
"createdAt": "2024-03-01T12:00:00.000000Z",
"updatedAt": "2024-03-01T12:00:00.000000Z",
"name": "Bebe Flatley",
"firstName": "Bebe",
"lastName": "Flatley",
"companyName": "Cubby",
"dateOfBirth": "1990-01-01",
"military": false,
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "",
"phone": "+15943590263",
},
"idType": "DRIVER_LICENSE | PASSPORT | STATE_ID | MILITARY_ID",
"idNumber": "123456789",
"leases": [
"lease_V4w64pjUwVK"
],
"leads": [
"lead_4a2da7d271a"
]
}
],
"leads": [
{
"leadId": "lead_4a2da7d271a",
"createdAt": "2024-03-01T12:00:00.000000Z",
"updatedAt": "2024-03-01T12:00:00.000000Z",
"source": "WALK_IN",
"status": "NEW",
"pricingGroupId": "pg_4a2da7d271a",
"message": "I'm interested in a 10x10 unit",
"targetMoveInDate": "2024-03-01"
}
]
}
}
Search for customers
Required Properties
customerId- limits results to a specific customer- or
organizationId- limits results to customers in a particular organization- or
facilityId- limits results to customers in a particular facility
Optional Properties
name- limits results to customers with a specific namephone- limits results to customers with a specific phone numberemail- limits results to customers with a specific email addresslease- if provided, limits results to either customers with an active lease (ACTIVE) or customers with any lease (ANY)lead- if provided, limits results to customers with a specific lead status (ACTIVEorANY)updatedAfter- limits results to customers whoseupdatedAtis strictly after the given UTC timestamp (ISO-8601, e.g.2024-03-01T12:00:00.000000Z). Use for incremental polling — pass the timestamp of your last sync to skip the boundary record on the next call.updatedBefore- limits results to customers whoseupdatedAtis strictly before the given UTC timestamp.expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint areleasesandleads
Customer Update
POST /v1/customers/update
Request Body — customers/update
{
"customerId": "cust_BqaN6zApXCH",
"name": "Bebe Flatley",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"zip": "15219"
},
"communicationPreferences": {
"smsMarketing": true,
"emailMarketing": false
}
}
Updates customer information. Only the fields that are to be updated need to be included in the request.
Required Properties
customerId- the ID of the tenant to update
Optional Properties
name- the name of the customercompanyName- the company name of the customercontact- an object containing the customer's contact and address information:address- the address of the customeraddress2- the second line of the address of the customercity- the city of the customerstate- the state of the customercountry- the country of the customerzip- the zip code of the customeremail- the email address of the customerphone- the phone number of the customer
dateOfBirth- the date of birth of the customermilitary- a boolean indicating if the customer is militaryidType- the type of ID the customer hasidNumber- the number of the ID the customer hascommunicationPreferences- an object controlling the customer's marketing opt-in per channel. Each flag is optional; omit a flag to leave that channel's current preference unchanged:smsMarketing- a boolean;trueopts in to promotional SMS,falserestricts SMS to transactional messages onlyemailMarketing- a boolean;trueopts in to promotional email,falserestricts email to transactional messages only
Leads
Leads Search
POST /v1/leads/search
Request Body — leads/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp"
},
"expansions": [ ... ]
}
Response Body — leads/search
{
"status": 200,
"data": {
"leads": [
{
"leadId": "lead_4a2da7d271a",
"createdAt": "2024-03-01T12:00:00.000000Z",
"updatedAt": "2024-03-05T09:30:00.000000Z",
"source": "WALK_IN",
"origin": "MANAGER",
"status": "RESERVATION",
"facilityId": "fac_C7bSZyPT6fp",
"pricingGroupId": "pg_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"message": "I'm interested in a 10x10 unit",
"targetMoveInDate": "2024-03-01",
"customerId": "cust_BqaN6zApXCH",
"coverageType": "ORGANISATION",
"coverageLevelId": "covlevel_4a2da7d271a",
"discounts": [ "discount_4a2da7d271a" ],
"rateType": "CUSTOM_RATE",
"customRate": 14900,
"reservedAt": "2024-03-03T15:42:00.000000Z",
"convertedAt": null,
"unqualifiedAt": null,
"leaseMoveInDate": null
}
]
}
}
Search for leads by facility
Required Properties
One of the following must be provided:
organizationId- limits results to leads in a particular organizationfacilityId- limits results to leads in a particular facilitycustomerId- limits results to leads for a particular customerpricingGroupId- limits results to leads for a particular pricing groupunitId- limits results to leads for a particular unitleadId- limits results to a specific lead
Optional Properties
updatedAfter- limits results to leads whoseupdatedAtis strictly after the given UTC timestamp (ISO-8601, e.g.2024-03-01T12:00:00.000000Z). Use for incremental polling — pass the timestamp of your last sync to skip the boundary record on the next call.updatedBefore- limits results to leads whoseupdatedAtis strictly before the given UTC timestamp.expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint arefacility,unit,pricingGroupandcustomer
Response Parameters
leadId- the ID of the leadcreatedAt- the date and time the lead was created, as an ISO-8601 UTC timestamp (e.g.2024-03-01T12:00:00.000000Z)updatedAt- the date and time the lead was last updated, as an ISO-8601 UTC timestamp (e.g.2024-03-01T12:00:00.000000Z)source- the source of the lead. Can be one of the following:WALK_INCALLCONTACT_FORMABANDONED_CHECKOUTFAILED_CHECKOUTRESERVED_CHECKOUTWEBSITE_CHECKOUTSMS_MESSAGEWAITLIST_FORMRESERVATION_FORMWEBSITEREFERRALSEARCH_ENGINEDIGITAL_ADBILLBOARDPHYSICAL_ADAI_VOICE_AGENTSPAREFOOTOTHER
customSource- a custom source for the lead, ifsourceisOTHERorigin- how the lead was created. Can be one of the following:MANAGER- manually created by a manager (seesource/customSourcefor the underlying channel)API- created through the external API (e.g.POST /v1/leads/create)AI_VOICE_AGENT- created by the AI voice agentCONTACT_FORM- submitted through a website contact formWAITLIST_FORM- submitted through a website waitlist formRESERVATION_FORM- submitted through a website reservation formWEBSITE_CHECKOUT- online checkout completed as a rentalRESERVED_CHECKOUT- online checkout completed as a reservationABANDONED_CHECKOUT- online checkout that was started but not completedFAILED_CHECKOUT- online checkout that failed at payment
status- the status of the lead. Can be one of the following:NEWON_HOLDIN_PROGRESS_HOTIN_PROGRESS_COLDCONVERTEDUNQUALIFIEDDUPLICATERESERVATION
facilityId- the ID of the facility the lead is interested inpricingGroupId- the ID of the pricing group the lead is interested inunitId- the ID of the unit the lead is interested inmessage- a free text message about the leadtargetMoveInDate- the target move-in date for the leadcustomerId- the ID of the customer associated with the leadcoverageType- the protection-plan coverage selected on the lead. One ofNONE,ORGANISATION(a facility coverage level), orPRIVATE_POLICY.nullif no coverage has been setcoverageLevelId- the ID of the selected coverage level whencoverageTypeisORGANISATION; otherwisenulldiscounts- an array of discount-program IDs applied to the lead; an empty array when none are appliedrateType- the quoted rate type on the lead. One ofWALK_IN_RATE,WEB_RATE, orCUSTOM_RATE.nullif unsetcustomRate- the custom monthly rate (in cents) quoted on the lead whenrateTypeisCUSTOM_RATE; otherwisenull
The coverage, discount, and rate assignments above are returned regardless of whether they were set through the API or by staff in the Cubby app.
reservedAt- ISO-8601 UTC timestamp when the lead transitioned into a reservation, ornullif it never did. For leads withorigin = RESERVATION_FORM, this equalscreatedAt.convertedAt- ISO-8601 UTC timestamp when the lead converted into a customer / lease, ornullif it has not convertedunqualifiedAt- ISO-8601 UTC timestamp when the lead was archived as unqualified (or, for reservation-origin leads, when the reservation was cancelled), ornullleaseMoveInDate- the start date of the lease created from this lead (YYYY-MM-DD), ornullif no lease has been created
Leads Create
POST /v1/leads/create
Request Body — leads/create
{
"organizationId": "org_4a2da7d271a",
"customerId": "cust_BqaN6zApXCH",
"source": "WALK_IN"
"customSource": "Google Ads",
"pricingGroupId": "pg_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"facilityId": "fac_C7bSZyPT6fp",
"message": "I'm interested in a 10x10 unit",
"targetMoveInDate": "2024-03-01",
"reservation": false,
"coverageLevelId": "covlevel_4a2da7d271a",
"discounts": [ "discount_4a2da7d271a" ],
"rateType": "CUSTOM_RATE",
"customRate": 14900,
"customer": {
"name": "Bebe Flatley",
"dateOfBirth": "1990-01-01",
"military": false,
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "",
"phone": "+15943590263"
},
"communicationPreferences": {
"smsMarketing": true,
"emailMarketing": false
}
}
}
Creates a new lead. If customerId is not provided, a new customer will be created.
Required Properties
organizationId- the ID of the organization the lead belongs to. At least one oforganizationIdorfacilityIdmust be providedfacilityId- the ID of the facility the lead is interested in. Can be used instead oforganizationIdfor facility-level API access. At least one oforganizationIdorfacilityIdmust be providedsource- the source of the lead, which can be one of the following:WALK_INCALLCONTACT_FORMABANDONED_CHECKOUTFAILED_CHECKOUTRESERVED_CHECKOUTWEBSITE_CHECKOUTSMS_MESSAGEWAITLIST_FORMRESERVATION_FORMWEBSITEREFERRALSEARCH_ENGINEDIGITAL_ADBILLBOARDPHYSICAL_ADAI_VOICE_AGENTSPAREFOOTOTHER
If source is OTHER, customSource must be provided.
Optional Properties
customerId- the ID of an existing customer. If not provided, a new customer will be created using thecustomerpropertycustomSource- a custom source for the lead. Required ifsourceisOTHER, otherwise ignoredunitId- the ID of the unit the lead is interested inpricingGroupId- the ID of the pricing group the lead is interested inmessage- a free text message about the leadtargetMoveInDate- the target move-in date for the leadreservation- a boolean indicating if the lead has a reservation, defaults tofalse. Iftrue,pricingGroupIdandtargetMoveInDatemust be providedcoverageLevelId- the ID of a facility coverage level to assign to the lead as its protection plan. The level must be active for the lead's facilitydiscounts- an array of discount-program IDs to apply to the lead. Each must be active and available for the lead's pricing group, sopricingGroupIdmust also be providedrateType- the quoted rate type for the lead. One ofWALK_IN_RATE,WEB_RATE, orCUSTOM_RATE. SettingCUSTOM_RATErequires the lead to have a facility or pricing groupcustomRate- the custom monthly rate to quote, in cents. Required whenrateTypeisCUSTOM_RATE; ignored otherwisecustomer.communicationPreferences- when creating a new customer, an object controlling the customer's marketing opt-in per channel. Each flag is optional; omit a flag to leave that channel at its default:smsMarketing- a boolean;trueopts in to promotional SMS,falserestricts SMS to transactional messages onlyemailMarketing- a boolean;trueopts in to promotional email,falserestricts email to transactional messages only
Leads Update
POST /v1/leads/update
Request Body — leads/update
{
"leadId": "lead_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"pricingGroupId": "pg_4a2da7d271a",
"status": "IN_PROGRESS_HOT",
"targetMoveInDate": "2024-03-01",
"coverageLevelId": "covlevel_4a2da7d271a",
"discounts": [ "discount_4a2da7d271a" ],
"rateType": "CUSTOM_RATE",
"customRate": 14900
}
Updates an existing lead. Only the fields to change need to be included: an omitted field is left unchanged, while an explicit null clears the value (where the field is clearable). The same validation rules as leads/create apply to the resulting lead.
To keep the endpoint predictable it does not perform reservation transitions: a lead that is already a reservation cannot be updated here, and status cannot be set to RESERVATION. status also cannot be set to CONVERTED — a lead becomes converted only when a lease is created for it, so a manual conversion is rejected.
Required Properties
leadId- the ID of the lead to update
Optional Properties
facilityId- reassign the lead to a different facilitypricingGroupId- the ID of the pricing group the lead is interested inunitId- the ID of the unit the lead is interested instatus- the status of the lead. One ofNEW,ON_HOLD,IN_PROGRESS_HOT,IN_PROGRESS_COLD,UNQUALIFIED, orDUPLICATE.RESERVATIONandCONVERTEDcannot be set through this endpointsource- the source of the lead. Cannot be changed for leads originating from a contact form or abandoned checkout, and cannot be clearedcustomSource- a custom source for the lead. Required whensourceisOTHERmessage- a free text message about the leadtargetMoveInDate- the target move-in date for the leadcoverageLevelId- the ID of a facility coverage level to assign as the lead's protection plan; an explicitnullclears coverage. The level must be active for the lead's facilitydiscounts- an array of discount-program IDs to apply to the lead; an explicitnullor empty array clears all discounts. Each must be active and available for the lead's pricing grouprateType- the quoted rate type for the lead. One ofWALK_IN_RATE,WEB_RATE, orCUSTOM_RATE. SettingCUSTOM_RATErequires the lead to have a facility or pricing groupcustomRate- the custom monthly rate to quote, in cents. Required in the same request wheneverrateTypeis set toCUSTOM_RATE; ignored otherwise
Leases
- Leases Search
- Leases Get Compliances
- Leases Get Rent Change Schedules
- Leases Change Rents
- Leases Cancel Rent Changes
- Lease Update Alternative Contacts
- Get Upsells
- Preview Charges
- Get Move-In Charges
- Create Lease
- Checkout
- Cancel Lease
- Schedule Move Out
- Get Payment Link
- Get Documents Link
- Make Payment
- Enable AutoPay
- Disable AutoPay
Leases Search
POST /v1/leases/search
Request Body — leases/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"activeOnOrAfter": "2024-03-01",
"activeOnOrBefore": "2024-03-31"
},
"expansions": [ ... ]
}
Response Body — leases/search
{
"status": 200,
"data": {
"leases": [
{
"leaseId": "lease_V4w64pjUwVK",
"createdAt": "2024-03-01T12:00:00.000000Z",
"updatedAt": "2024-03-01T12:00:00.000000Z",
"moveInDate": "2024-03-06",
"moveOutDate": null,
"monthlyRentalAmount": 20800,
"paidThroughDate": "2024-03-06",
"nextChargeAmount": 22672,
"nextChargeDate": "2024-04-06",
"delinquencyStartDate": null,
"overlockNeeded": false,
"alternativeContacts": [
{
"name": "Tyrell Maurice",
"phone": "+122233344455",
"email": "tyrel@test.test.test"
}
],
"coverage": {
"coverageType": "ORGANISATION",
"startDate": "2024-05-01",
"coverageLevelId": "covlevel_4a2da7d271a",
"premiumAmount": 1500,
"coverageAmount": 100000
},
"coverageChange": {
"coverageType": "ORGANISATION",
"startDate": "2024-06-01",
"coverageLevelId": "covlevel_341f3jNjKuf",
"premiumAmount": 2000,
"coverageAmount": 150000
},
"privatePolicyNumber": null,
"privatePolicyExpirationDate": null,
"coverageAutoenrollable": true,
"unitContents": "Personal vehicle",
"storingVehicle": true,
"vehicle": {
"type": "SEDAN | SUV | TRUCK | RV | TRAILER | BOAT | PLANE | MOTORCYCLE | OTHER",
"licenseNumber": "ABC123",
"state": "MN"
},
"customerId": "cust_BqaN6zApXCH",
"unitId": "unit_GfNkzV4itfk",
"pricingGroupId": "pg_4a2da7d271a",
"facilityId": "fac_C7bSZyPT6fp",
"rentChangeScheduledDate": "2024-06-01",
"rentChangeNewRentAmount": 22000,
"scheduledMoveOut": {
"moveOutDate": "2024-07-01",
"noticeGivenDate": "2024-06-01",
"moveOutReason": "OTHER",
"customReason": "Moving to a new city",
"moveOutTime": "MORNING"
}
}
],
"customers": [
{
"customerId": "cust_BqaN6zApXCH",
"createdAt": "2024-03-01T12:00:00.000000Z",
"updatedAt": "2024-03-01T12:00:00.000000Z",
"name": "Bebe Flatley",
"firstName": "Bebe",
"lastName": "Flatley",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "bebe.flatley@example.org",
"phone": "+15943590263"
}
}
],
"units": [],
"pricingGroups": [],
"facilities": [],
"ledgers": [],
"compliances": []
}
}
Returns metadata for leases at co-managed facilities
Required Properties
leaseId- limits results to a specific lease- or
facilityId- limits results to leases in a particular facility- or
customerId- limits results to leases for a particular customer
Optional Properties
activeOnOrAfter- limits results to leases which are active on or after a specific dateactiveOnOrBefore- limits results to leases which are active on or before a specific dateupdatedAfter- limits results to leases whoseupdatedAtis strictly after the given UTC timestamp (ISO-8601, e.g.2024-03-01T12:00:00.000000Z). Use for incremental polling — pass the timestamp of your last sync to skip the boundary record on the next call.updatedBefore- limits results to leases whoseupdatedAtis strictly before the given UTC timestamp.expansions- an array of strings which can be used to include additional data in the response; supported for this- endpoint are
facility,unit,pricingGroupledger,customer,compliance
Response Properties
createdAt- the date and time the lease was created, as an ISO-8601 UTC timestamp (e.g.2024-03-01T12:00:00.000000Z)updatedAt- the date and time the lease was last updated, as an ISO-8601 UTC timestamp (e.g.2024-03-01T12:00:00.000000Z)nextChargeAmount- total amount that will be charged onnextChargeDateincluding insurance, additional fees and taxes. Will be populated only when searching byleaseIdorcustomerIdcoverage- the current coverage details for the lease:coverageType- the type of coverage, which can beORGANISATIONfor organization-provided coverage,PRIVATE_POLICYfor tenant-provided coverage orNONEfor no coverage required- If
coverageTypeisORGANISATION:startDate- the date the coverage startedcoverageLevelId- the ID of the coverage level for the leasepremiumAmount- the current premium amount in centscoverageAmount- the current coverage amount in cents
coverageChange- the next scheduled coverage change for the lease, if such change exists:coverageType- the type of coverage for the upcoming change, which can beORGANISATIONfor organization-provided coverage,PRIVATE_POLICYfor tenant-provided coverage orNONEfor no coverage requiredstartDate- the date the coverage change will take effectcoverageLevelId- the ID of the new coverage level for the lease, if the coverage change is to organization-provided coveragepremiumAmount- the new premium amount in centscoverageAmount- the new coverage amount in cents
scheduledMoveOut- details about a scheduled move-out for the lease, if one exists:moveOutDate- the date the tenant will move out (YYYY-MM-DD)noticeGivenDate- the date the tenant gave notice (YYYY-MM-DD)moveOutReason- the reason for moving out; one ofNONE,CANT_AFFORD,NO_NEED,MOVING,CONSOLIDATING,BAD_EXPERIENCE,AUCTION, orOTHERcustomReason- a custom reason for the move-out, present whenmoveOutReasonisOTHERmoveOutTime- the preferred time of day for the move-out; one ofMORNING,LUNCHTIME,AFTERNOON,EVENING, orANYTIME
Leases Get Compliances
POST /v1/leases/get-compliances
Request Body — leases/get-compliances
{
"leaseIds": [
"lease_V4w64pjUwVK"
]
}
Response Body — leases/get-compliances
{
"status": 200,
"data": {
"compliances": [
{
"leaseId": "lease_V4w64pjUwVK",
"documents": [
{
"type": "LEASE_AGREEMENT | COVERAGE | IDENTITY | VEHICLE",
"status": "NOT_REQUIRED" | "INCOMPLETE" | "PENDING_APPROVAL" | "SIGNATURE_NEEDED" | "REJECTED" | "APPROVED"
}
]
},
{/* ... */}
]
}
}
Returns the compliance status for leases
Required Properties
leaseIds- an array of lease IDs to get compliance status for
Response Parameters
leaseId- the ID of the leasedocuments- an array of documents required for the lease to be compliant, each containingtype- the type of the document, which can be one of the following:LEASE_AGREEMENTCOVERAGEIDENTITYVEHICLE
status- the status of the document, which can be one of the following:NOT_REQUIREDINCOMPLETEPENDING_APPROVALSIGNATURE_NEEDEDREJECTEDAPPROVED
Leases Get Rent Change Schedules
POST /v1/leases/get-rent-change-schedules
Request Body — leases/get-rent-change-schedules
{
"leaseIds": [
"lease_V4w64pjUwVK"
]
}
Response Body — leases/get-rent-change-schedules
{
"status": 200,
"data": {
"rentChangeSchedules": [
{
"leaseId": "lease_V4w64pjUwVK",
"rentChangeDate": "2024-06-01",
"noticeDate": "2024-05-01",
},
{/* ... */}
]
}
}
Returns the next possible rent change schedule for leases
Required Properties
leaseIds- an array of lease IDs to get rent change schedules for
Response Parameters
leaseId- the ID of the leaserentChangeDate- the date the rent change will take effectnoticeDate- the date the rent change notice will be sent
Leases Change Rents
POST /v1/leases/change-rents
Request Body — leases/change-rents
{
"leases": [
{
"leaseId": "lease_V4w64pjUwVK",
"newRentAmount": 22000,
"rentChangeDate": "2024-06-01",
"noticeDate": "2024-05-01",
}
]
}
Schedules rent changes for leases, which will take effect on the next possible rent change date for each lease
Required Properties
leases- an array of lease rent change objects, each containing:leaseId- the ID of the lease to change the rent fornewRentAmount- the new rent amount in cents
Optional Properties
rentChangeDate- the date the rent change will take effect, as returned by the get rent change schedules endpoint; if not provided, the next possible rent change date will be usednoticeDate- the date the rent change notice will be sent, as returned by the get rent change schedules endpoint; if not provided, the notice date will be set to 30 days before the rent change date
Leases Cancel Rent Changes
POST /v1/leases/cancel-rent-changes
Request Body — leases/cancel-rent-changes
{
"leaseIds": [
"lease_V4w64pjUwVK"
]
}
Cancels scheduled rent changes for leases
Lease Update Alternative Contacts
POST /v1/leases/update-alternative-contacts
Request Body — leases/update-alternative-contacts
{
"leaseId": "lease_V4w64pjUwVK",
"alternativeContacts": [
{
"name": "Tyrell Maurice",
"phone": "+122233344455",
"email": "tyrel@test.test.test"
}
]
}
Updates the alternative contacts for a lease
Required Properties
leaseId- the ID of the lease to updatealternativeContacts- an array of alternative contacts
Get Upsells
POST /v1/leases/get-upsells
Request Body — leases/get-upsells
{
"unitId": "unit_GfNkzV4itfk",
"rentAmount": 20800
}
Response Body — leases/get-upsells
{
"status": 200,
"data": {
"upsells": [
{
"feeId": "fee_3kLmN2pQrSt",
"name": "Climate Control Upgrade",
"description": "Keeps your unit between 55°F and 85°F year-round",
"amount": 1500
},
{
"feeId": "fee_8XyZab9CdEf",
"name": "Premium Access Hours",
"description": "24/7 facility access",
"amount": 500
}
]
}
}
Returns the optional upsell (upgrade) recurring fees available for a unit. Each upsell can be
opted into at move-in by passing its feeId in the upsellFeeIds array of
Get Move-In Charges, Create Lease, or
Checkout. Only active fees configured as optional upgrades on the unit's pricing
group are returned. The amount is the recurring charge per billing cycle; for
percentage-based fees it is computed against the supplied rentAmount (or the pricing
group's standard rate when rentAmount is omitted), so the preview matches what the same
rentAmount will be billed in Get Move-In Charges and
Create Lease.
Required Properties
unitId- the ID of the unit
Optional Properties
rentAmount- the rent amount to use as the base when computing percentage-based fee amounts. Defaults to the pricing group's standard rate. Pass the same value here as on Get Move-In Charges or Create Lease to get a preview that matches the billed amount.
Preview Charges
POST /v1/leases/preview-charges
Request Body — leases/preview-charges
{
"leaseId": "lease_jOi8joH3Hu",
"prepayMonths": 3,
"paymentMethodId": "pm_V4w64pjUwVK"
}
Response Body — leases/preview-charges
{
"status": 200,
"data": {
"subtotal": 16710,
"tax": 1545,
"totalBeforePayments": 18255,
"totalPaid": 0,
"prepaidBalance": 0,
"total": 18255,
"charges": [
{
"type": "RENT",
"displayName": "Rent",
"description": "$61.00 (monthly rate) x 3 months",
"accruesOn": "2026-06-01",
"accruesThrough": "2026-08-31",
"amount": 12810,
"undiscountedAmount": 18300,
"discounts": [ "Summer Special" ]
},
{
"type": "INSURANCE",
"displayName": "Coverage",
"description": "",
"accruesOn": "2026-06-01",
"accruesThrough": "2026-08-31",
"amount": 2400,
"undiscountedAmount": 2400,
"discounts": []
},
{
"type": "FEES",
"displayName": "Admin Fee",
"description": "",
"amount": 1500,
"undiscountedAmount": 1500,
"discounts": []
}
]
}
}
Returns a charges breakdown for an existing lease. With no prepayMonths, it returns the lease's current
outstanding charges. When prepayMonths is provided, the response also includes the projected charges for
prepaying that many billing periods, so total reflects the full cost to bring the lease current and
prepay ahead. Any amount already paid toward the outstanding charges (totalPaid) and the lease's prepaid
credit balance (prepaidBalance) are deducted from totalBeforePayments to produce total, so total is
the amount that would actually be collected. Projected charges account for discounts applied to the specific
months they cover (not averaged across the period), coverage premiums, recurring fees, and taxes. All
monetary values are in cents.
When paymentMethodId is supplied and resolves to a credit-card method at a facility with credit-card
processing fees configured, the fee is added to the breakdown (as a FEES charge) and included in
subtotal, tax, totalBeforePayments, and total, so total equals the amount to send to
Make Payment with that method to fully settle the charges. Omit paymentMethodId (or
supply a non-credit method, or a facility with no fee configured) to get the fee-free charges.
Required Properties
leaseId- the ID of the lease
Optional Properties
prepayMonths- the number of billing periods to prepay. Omit (ornull) to return only the current outstanding charges. Defaults tonull.paymentMethodId- a saved payment method to preview the payment against. When it is a credit-card method and the facility has credit-card processing fees configured, the returned totals include that fee. Must belong to the lease's customer. Omit (ornull) to exclude credit-card fees. Defaults tonull.
Response Parameters
| Parameter | Description |
|---|---|
subtotal |
Subtotal in cents before tax |
tax |
Tax amount in cents |
totalBeforePayments |
Charges in cents before deducting payments and prepaid balance (subtotal + tax) |
totalPaid |
Amount in cents already paid toward the outstanding charges |
prepaidBalance |
The lease's prepaid (credit) balance in cents, applied to offset the charges |
total |
Amount in cents still owed, after deducting totalPaid and prepaidBalance (floored at zero) |
charges[].type |
Charge category. One of RENT, INSURANCE, FEES, DEPOSIT. Taxes are summed into tax and discounts are folded into the parent charge's discounts, so they are not returned as separate charges |
charges[].displayName |
Human-readable name of the charge |
charges[].description |
Charge description (e.g. "$61.00 (monthly rate) x 3 months"), may be empty |
charges[].accruesOn |
Charge period start date (ISO-8601), omitted for point charges |
charges[].accruesThrough |
Charge period end date (ISO-8601), omitted for point charges |
charges[].amount |
Charge amount in cents, after discounts |
charges[].undiscountedAmount |
Charge amount in cents, before discounts |
charges[].discounts |
Names of the discount programs applied to the charge |
Error Conditions
404- the lease was not found
Get Move-In Charges
POST /v1/leases/get-move-in-charges
Request Body — leases/get-move-in-charges
{
"unitId": "unit_GfNkzV4itfk",
"moveInDate": "2024-03-06",
"rentAmount": 20800,
"coverageLevelId": "covlevel_4a2da7d271a",
"chargeDeposit": true,
"chargeMoveInFee": true,
"taxExempt": false,
"storingVehicle": true,
"discounts": [ "discount_JgNkzV4itfk" ],
"upsellFeeIds": [ "fee_3kLmN2pQrSt" ]
}
Response Body — leases/get-move-in-charges
{
"status": 200,
"data": {
"subtotal": 34300,
"tax": 2898,
"total": 37198,
"charges": [
{
"accruesOn": "2024-10-21",
"accruesThrough": "2024-11-20",
"type": "RENT",
"displayName": "Rent",
"description": "",
"amount": 21000,
"undiscountedAmount": 21000,
"discounts": []
},
{
"type": "COVERAGE",
"displayName": "Coverage",
"description": "",
"accruesOn": "2024-10-21",
"accruesThrough": "2024-11-20",
"amount": 800,
"undiscountedAmount": 800,
"discounts": []
},
{
"type": "FEES",
"displayName": "Move-in Fee",
"description": "",
"amount": 2500,
"undiscountedAmount": 2500,
"discounts": []
},
{
"type": "DEPOSIT",
"displayName": "Security Deposit",
"description": "",
"amount": 10000,
"undiscountedAmount": 10000,
"discounts": []
}
]
}
}
Returns the charges for a lease move-in
Required Properties
unitId- the ID of the unitmoveInDate- the date the tenant is moving inrentAmount- the rent amount
Optional Properties
coverageLevelId- the ID of the coverage level, defaults tonullchargeDeposit- a boolean indicating if the deposit should be charged, defaults totruechargeMoveInFee- a boolean indicating if the move-in fee should be charged, defaults totruetaxExempt- a boolean indicating if the charges are tax exempt, defaults tofalsestoringVehicle- a boolean indicating whether the tenant is storing a vehicle. Determines which tax category applies to rent, so it should match the value sent to Create Lease / Checkout to get a matching total. Defaults to the unit's pricing group parking setting.discounts- an array of discount IDs, defaults to[]upsellFeeIds- an array of upsell fee IDs to include as recurring charges on the lease. Each ID must come from Get Upsells for the sameunitId; passing a fee that is not an active optional upgrade for the unit returns a400error. Defaults to[].
Create Lease
POST /v1/leases/create
Creates a new lease without collecting payment. Use this endpoint when payment is handled separately or is not required at move-in time. To create a lease and collect payment in a single step, use the Checkout endpoint instead.
Request Body — leases/create
{
"unitId": "unit_GfNkzV4itfk",
"moveInDate": "2024-03-06",
"rentAmount": 20800,
"coverageLevelId": "covlevel_4a2da7d271a",
"chargeDeposit": true,
"chargeMoveInFee": true,
"taxExempt": false,
"storingVehicle": true,
"discounts": [ "discount_JgNkzV4itfk" ],
"upsellFeeIds": [ "fee_3kLmN2pQrSt" ],
"customerId": "cust_BqaN6zApXCH",
"customer": {
"name": "Bebe Flatley",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "bebe.flatley@example.org",
"phone": "+15943590263"
},
"communicationPreferences": {
"smsMarketing": true,
"emailMarketing": false
}
},
"source": "WEBSITE",
"customSource": null
}
Response Body — leases/create
{
"status": 200,
"data": {
"leaseId": "lease_V4w64pjUwVK"
}
}
Required Properties
-
unitId- the ID of the unit -
moveInDate- the date the tenant is moving in -
rentAmount- the rent amount -
customerId- the ID of the tenant -
or
-
customer- the tenant information: -
name- the name of the tenant
-
phone- the phone number of the tenant
Optional Properties
coverageLevelId- the ID of the coverage level, defaults tonullchargeDeposit- a boolean indicating if the deposit should be charged, defaults totruechargeMoveInFee- a boolean indicating if the move-in fee should be charged, defaults totruetaxExempt- a boolean indicating if the charges are tax exempt, defaults tofalsestoringVehicle- a boolean indicating whether the tenant is storing a vehicle. Whentrue, the vehicle storage addendum is attached to the lease for signing. Defaults to the unit's pricing group parking setting.discounts- an array of discount IDs, defaults to[]upsellFeeIds- an array of upsell fee IDs to add as recurring charges on the lease. Each ID must come from Get Upsells for the sameunitId; passing a fee that is not an active optional upgrade for the unit returns a400error. Defaults to[].source- the lead source, defaults toOTHER. One of:WALK_IN,CALL,CONTACT_FORM,WEBSITE,REFERRAL,SEARCH_ENGINE,DIGITAL_AD,BILLBOARD,PHYSICAL_AD,AI_VOICE_AGENT,SPAREFOOT,OTHERcustomSource- a custom source description, used whensourceisOTHERalternativeContacts- an array of alternative contacts for the leasecustomer- the tenant information:-
name- the name of the tenant
-
dateOfBirth- the date of birth of the tenant
-
military- a boolean indicating if the tenant is military
-
contact- the tenant's contact and address information:
-
-
address- the address of the tenant
-
-
-
address2- the second line of the address of the tenant
-
-
-
city- the city of the tenant
-
-
-
state- the state of the tenant
-
-
-
country- the country of the tenant
-
-
-
zip- the zip code of the tenant
-
-
-
email- the email address of the tenant
-
-
-
phone- the phone number of the tenant
-
-
communicationPreferences- an object controlling the new customer's marketing opt-in per channel. Each flag is optional; omit a flag to leave that channel at its default:
-
-
smsMarketing- a boolean;trueopts in to promotional SMS,falserestricts SMS to transactional messages only
-
-
-
emailMarketing- a boolean;trueopts in to promotional email,falserestricts email to transactional messages only
-
Checkout
POST /v1/leases/checkout
Creates a new lease and collects payment for the move-in charges in a single step.
Accepts all the same fields as Create Lease, plus a required payment
object.
A lead is created first, then the lease is created and the move-in charges are charged.
If the payment is declined, the lease is rolled back but the lead survives. If the payment
succeeds, the response includes the leaseId, paymentTransactionId, and
paymentSuccess: true. If the payment is declined, leaseId is null,
paymentSuccess is false, and paymentFailureInfo contains the reason.
When enableAutoPay is true, a successful payment also saves the card supplied in payment
to the customer as a reusable payment method and enrols the new lease in AutoPay using that
card. Saving the card and enabling AutoPay happen after the charge and never affect it: if
either step fails the payment still stands, and the paymentMethodId and autoPayEnabled
response fields report the outcome of each. When enableAutoPay is omitted or false, the
card is charged but not saved — paymentMethodId is null and autoPayEnabled is false.
The payment.amount must match the total from Get Move-In Charges
exactly, otherwise a 400 error is returned.
Request Body — leases/checkout
{
"unitId": "unit_GfNkzV4itfk",
"moveInDate": "2024-03-06",
"rentAmount": 20800,
"coverageLevelId": "covlevel_4a2da7d271a",
"chargeDeposit": true,
"chargeMoveInFee": true,
"taxExempt": false,
"storingVehicle": true,
"discounts": [ "discount_JgNkzV4itfk" ],
"upsellFeeIds": [ "fee_3kLmN2pQrSt" ],
"customerId": "cust_BqaN6zApXCH",
"customer": {
"name": "Bebe Flatley",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "bebe.flatley@example.org",
"phone": "+15943590263"
}
},
"source": "WEBSITE",
"customSource": null,
"enableAutoPay": true,
"payment": {
"amount": 37198,
"address": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "bebe.flatley@example.com",
"phone": "+15943590263"
},
"methodType": "CREDIT_CARD",
"token": "tok_1Hh1XYZabc1234567890",
"cardBrand": "VISA",
"cardExpiration": "03/24",
"cardLastFour": "1234",
"cardHolder": "Bebe Flatley"
}
}
Response Body (success) — leases/checkout
{
"status": 200,
"data": {
"leaseId": "lease_V4w64pjUwVK",
"paymentTransactionId": "ptxn_8kLmN2pQrSt",
"paymentSuccess": true,
"paymentMethodId": "pm_V4w64pjUwVK",
"autoPayEnabled": true
}
}
Response Body (declined) — leases/checkout
{
"status": 200,
"data": {
"leaseId": null,
"paymentTransactionId": "ptxn_8kLmN2pQrSt",
"paymentSuccess": false,
"paymentFailureInfo": {
"reason": "Insufficient funds"
},
"paymentMethodId": null,
"autoPayEnabled": false
}
}
Required Properties
All properties from Create Lease, plus:
payment- payment information for the move-in charges:-
amount- the amount to be charged (must equal the total from get-move-in-charges)
-
methodType- the type of payment method. OnlyCREDIT_CARDis supported on this endpoint. To charge anACHorACSSmethod, save it via Create Payment Method and charge it with Make Payment.
-
token- the token generated by the payment gateway
-
address- the billing address associated with the payment method:
-
address- the street address
-
address2- the second line of the street address
-
city- the city
-
state- the state
-
country- the country
-
zip- the zip code
-
email- the email address
-
phone- the phone number
- If
methodTypeisCREDIT_CARD, the following properties are also required:cardBrand- the brand of the credit card, which can be one of the following:VISAMASTERCARDAMERICAN_EXPRESSDISCOVERDINERS_CLUBJCBMAESTROUNIONPAYMIRELOHIPERHIPERCARDFORBRUGSFORENINGENVISA_ELECTRONUNKNOWN
cardExpiration- the expiration date of the credit card in MM/YY formatcardLastFour- the last four digits of the credit cardcardHolder- the name of the cardholder
Optional Properties
All optional properties from Create Lease also apply, plus:
enableAutoPay- a boolean (defaults tofalse). Whentrue, a successful payment saves the card supplied inpaymentto the customer as a reusable payment method and enrols the lease in AutoPay using it. Whenfalse, the card is charged but not saved. AutoPay is only enabled when the payment succeeds and the card is saved; check theautoPayEnabledresponse flag to confirm.
Response Parameters
leaseId- the ID of the created lease;nullif the payment was declinedpaymentTransactionId- the ID of the payment transactionpaymentSuccess- whether the move-in payment succeeded. Whenfalse, the lease was rolled backpaymentFailureInfo- present only when the payment failed; contains the declinereason. It is not used to report card-save or AutoPay problemspaymentMethodId- the ID of the saved payment method, ornullwhen the card was not saved to the customer as a reusable payment method. The card is saved only whenenableAutoPayistrue, so this is alwaysnullwhen AutoPay was not requested. When AutoPay was requested and the payment succeeded, anullvalue means the charge went through but the card could not be stored (so AutoPay was not enabled). When non-null, it can be reused for subsequent payments (e.g. Make Payment) or AutoPay for this customerautoPayEnabled- whether AutoPay was enabled for the lease. OnlytruewhenenableAutoPaywas requested and the card was saved successfully
Cancel Lease
POST /v1/leases/cancel-lease
Request Body — leases/cancel-lease
{
"leaseId": "lease_V4w64pjUwVK"
}
Cancels a lease which has not yet started (i.e. the move-in date is in the future)
Required Properties
leaseId- the ID of the lease to cancel
Schedule Move Out
POST /v1/leases/schedule-move-out
Request Body — leases/schedule-move-out
{
"leaseId": "lease_V4w64pjUwVK",
"moveOutDate": "2026-04-01",
"noticeGivenDate": "2026-02-24",
"moveOutReason": "NO_NEED",
"customReason": null,
"moveOutTime": "MORNING",
"disableAutoPay": true
}
Schedules a move-out for a lease
Required Properties
leaseId- the ID of the lease to schedule the move-out formoveOutDate- the date the tenant will move out (YYYY-MM-DD)noticeGivenDate- the date the tenant gave notice (YYYY-MM-DD)moveOutReason- the reason for moving out; one ofNONE,CANT_AFFORD,NO_NEED,MOVING,CONSOLIDATING,BAD_EXPERIENCE,AUCTION, orOTHERmoveOutTime- the preferred time of day for the move-out; one ofMORNING,LUNCHTIME,AFTERNOON,EVENING, orANYTIMEdisableAutoPay- a boolean indicating whether to disable auto-pay for the lease
Optional Properties
customReason- a custom reason for the move-out (required ifmoveOutReasonisOTHER)
Get Payment Link
POST /v1/leases/get-payment-link
Request Body — leases/get-payment-link
{
"leaseIds": ["lease_V4w64pjUwVK", "lease_GfNkzV4itfk"]
}
Response Body — leases/get-payment-link
{
"status": 200,
"data": {
"paymentLink": "https://pay.example.com/1?token=abc123"
}
}
Generates a payment link which can be sent to the tenant to make a payment for one or more leases
Required Properties
leaseIds- an array of lease IDs to include in the payment link
Get Documents Link
POST /v1/leases/get-documents-link
Request Body — leases/get-documents-link
{
"leaseId": "lease_V4w64pjUwVK"
}
Response Body — leases/get-documents-link
{
"status": 200,
"data": {
"documentsLink": "https://portal.example.com/leases/lease_1/documents?token=abc123"
}
}
Generates a link which can be sent to the tenant to view, manage, and sign documents for a lease.
Required Properties
leaseId- the ID of the lease to generate a documents link for
Make Payment
POST /v1/leases/make-payment
Request Body — leases/make-payment
{
"leaseId": "lease_V4w64pjUwVK",
"paymentMethodId": "pm_V4w64pjUwVK",
"amount": 1500
}
Makes a payment for a lease using a saved payment method. If the amount paid is more than the amount due, the overpayment will be transferred to the prepaid balance of the lease.
When the payment method is a credit card and the facility has credit-card processing fees configured in its payment settings, the fee is deducted from amount — the card is charged exactly amount, and the remainder is applied to the lease. To fully settle a balance in this case, charge the fee-inclusive total returned by Preview Charges for the same paymentMethodId. Facilities without credit-card fees configured are unaffected.
Required Properties
leaseId- the ID of the lease to make a payment forpaymentMethodId- the ID of the payment method to useamount- the amount in cents to charge the payment method. For credit cards at facilities with processing fees configured, the fee is included in (deducted from) this amount.
Enable AutoPay
POST /v1/leases/enable-auto-pay
Request Body — leases/enable-auto-pay
{
"leaseId": "lease_V4w64pjUwVK",
"paymentMethodId": "pm_V4w64pjUwVK"
}
Enables AutoPay for a lease using a saved payment method. With AutoPay enabled, the tenant will be automatically charged for the amount due on the next charge date of the lease, and on subsequent charge dates until AutoPay is disabled.
Required Properties
leaseId- the ID of the lease to enable AutoPay forpaymentMethodId- the ID of the payment method to use for AutoPay
Disable AutoPay
POST /v1/leases/disable-auto-pay
Request Body — leases/disable-auto-pay
{
"leaseId": "lease_V4w64pjUwVK"
}
Disables AutoPay for a lease.
Payment Methods
Payment Methods Search
POST /v1/payment-methods/search
Request Body — payment-methods/search
{
"where": {
"customerId": "cust_BqaN6zApXCH"
}
}
Response Body — payment-methods/search
{
"status": 200,
"data": {
"paymentMethods": [
{
"paymentMethodId": "pm_V4w64pjUwVK",
"type": "CREDIT_CARD | ACH",
"cardBrand": "VISA | MASTERCARD | AMERICAN_EXPRESS | DISCOVER | DINERS_CLUB | JCB | MAESTRO | UNIONPAY | MIR | ELO | HIPER | HIPERCARD | FORBRUGSFORENINGEN | VISA_ELECTRON | UNKNOWN",
"cardLastFour": "1234",
"cardExpiration": "03/24",
"achAccountLastFour": "1234",
"achAccountType": "CHECKING | SAVINGS"
}
]
}
}
Search for saved payment methods by customer
Required Properties
customerId- the ID of the customer
Generating a Payment Token
Before creating a payment method in Cubby, you must first generate a single-use token through
your organization's payment gateway. The token is then passed to the
Create Payment Method endpoint below as the token property.
Cubby supports two payment gateways — Stripe and Payabli — configured per facility. A
given facility uses exactly one of them. To determine which gateway a facility uses, call the
Facilities Search endpoint and read the paymentServiceProvider field
(STRIPE or PAYABLI) on the facility. Cubby provides the corresponding publishable key. Follow
the flow for that facility's gateway below; the resulting token is sent to the Cubby API in
exactly the same way regardless of gateway.
Stripe
Use this flow for facilities whose paymentServiceProvider is STRIPE. Your Stripe publishable
key (STRIPE_PK) will be provided by Cubby.
Begin by loading the Stripe.js library on the page where you collect card details.
Step 1a: Load Stripe.js
<script src="https://js.stripe.com/clover/stripe.js"></script>
With the library loaded, create a Stripe instance with your publishable key and an Elements group
in setup mode with manual payment-method creation. This renders the card input fields your
customer will fill in.
Step 1b: Initialize Stripe Elements
const stripe = Stripe(STRIPE_PK);
const stripeElements = stripe.elements({
loader: 'auto',
mode: 'setup',
currency: 'usd',
payment_method_types: ['card'],
paymentMethodCreation: 'manual',
});
Once the customer has entered their card details, submit the Elements form and create a payment
method, supplying the cardholder's billing details. The resulting paymentMethod.id is the token
you will pass to the Cubby API.
Step 2: Create a Stripe payment method
await stripeElements.submit();
const { paymentMethod, error } = await stripe.createPaymentMethod({
elements: stripeElements,
params: {
billing_details: {
name: 'Bebe Flatley',
email: 'bebe.flatley@example.com',
phone: '+15943590263',
address: {
country: 'US',
postal_code: '15219',
state: null,
city: null,
line1: null,
line2: null,
},
},
},
});
Payabli
Use this flow for facilities whose paymentServiceProvider is PAYABLI. Payabli card capture is
powered by Basis Theory web elements; install the
@basis-theory/web-elements package to begin.
First, add a container element to your page. Basis Theory will mount its secure card input into this element.
Step 1a: Add a mount point
<div id="card-element"></div>
Initialize Basis Theory with the publishable key (BT_PK) and environment (test or
production) provided by Cubby, then create a card element and mount it into the container you
just added.
Step 1b: Initialize Basis Theory
import { basistheory } from '@basis-theory/web-elements';
const bt = await basistheory(BT_PK, { environment: 'test' });
const cardElement = bt.createElement('card', {
autoComplete: {
number: 'on',
expirationDate: 'on',
csc: 'on',
},
});
cardElement.mount('#card-element');
Once the customer has entered their card details, create a token intent from the card element.
The resulting token.id is the token you will pass to the Cubby API.
Step 2: Create a Basis Theory token
const token = await bt.tokenIntents.create({
type: 'card',
data: cardElement,
});
Send the token to Cubby
Use the token produced by your gateway — Stripe's paymentMethod.id or Basis Theory's token.id
— as the token value in the Create Payment Method endpoint below.
Create Payment Method
POST /v1/payment-methods/create
Request Body — payment-methods/create
{
"token": "tok_1Hh1XYZabc1234567890",
"methodType": "CREDIT_CARD",
"cardBrand": "VISA",
"cardExpiration": "03/24",
"cardLastFour": "1234",
"cardHolder": "Bebe Flatley",
"customerId": "cust_BqaN6zApXCH",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "bebe.flatley@example.com",
"phone": "+15943590263"
}
}
Response Body — payment-methods/create
{
"status": 200,
"data": {
"paymentMethodId": "pm_V4w64pjUwVK"
}
}
Creates a new payment method for a customer using a token generated by the payment gateway.
The caller must ensure the payment method has been successfully validated and authorized by the payment gateway before submission. Unvalidated payment methods may be rejected by the payment gateway when used for a transaction.
Required Properties
methodType- the type of payment method, which can beCREDIT_CARD,ACHorACSStoken- the token generated by the payment gatewaycustomerId- the ID of the customeraddress- the billing address associated with the payment method:address- the street addressaddress2- the second line of the street addresscity- the citystate- the statecountry- the countryzip- the zip codeemail- the email addressphone- the phone number
- If
methodTypeisCREDIT_CARD, the following properties are also required:cardBrand- the brand of the credit card, which can be one of the following:VISAMASTERCARDAMERICAN_EXPRESSDISCOVERDINERS_CLUBJCBMAESTROUNIONPAYMIRELOHIPERHIPERCARDFORBRUGSFORENINGENVISA_ELECTRONUNKNOWNcardExpiration- the expiration date of the credit card in MM/YY formatcardLastFour- the last four digits of the credit cardcardHolder- the name of the cardholder
- If
methodTypeisACH, the following properties are also required:achAccountType- the type of ACH account, which can beCHECKINGorSAVINGSachAccountHolder- the name of the account holderachAccountLastFour- the last four digits of the ACH account
- If
methodTypeisACSS, the following properties are also required:acssAccountHolderType- the type of ACSS account holder, which can bePERSONALorBUSINESSacssAccountHolder- the name of the account holderacssAccountLastFour- the last four digits of the ACSS account
Ledgers
Ledger Search
POST /v1/ledgers/search
Request Body — ledgers/search
{
"where": {
"leaseId": "lease_V4w64pjUwVK",
"facilityId": "fac_C7bSZyPT6fp"
}
}
Response Body — ledgers/search
{
"status": 200,
"data": {
"ledgers": [
{
"leaseId": "lease_NpZ1BGBoWrS",
"balances": {
"totalDue": 1500,
"deposit": 20000,
"prepaid": 0
},
"bookEntries": [
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:50.689691",
"amount": 2500,
"amountPaid": 2500,
"paymentTime": "2024-08-26T07:30:50.826992",
"details": {
"category": "FEE",
"description": "Move-in Fee",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:50.689691",
"amount": 20000,
"amountPaid": 20000,
"paymentTime": "2024-08-26T07:30:50.826992",
"details": {
"category": "DEPOSIT",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:50.689691",
"amount": 10000,
"amountPaid": 10000,
"paymentTime": "2024-08-26T07:30:50.826992",
"details": {
"category": "RENT",
"accruesOn": "2024-01-01"
"accruesThrough": "2024-01-31",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:50.689691",
"amount": 450,
"amountPaid": 450,
"paymentTime": "2024-08-26T07:30:50.826992",
"details": {
"category": "TAX_STATE",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"description": "4.5%",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:50.689691",
"amount": 50,
"amountPaid": 50,
"paymentTime": "2024-08-26T07:30:50.826992",
"details": {
"category": "TAX_LOCAL",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"description": "0.5%",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "PAYMENT",
"entryTime": "2024-08-26T07:30:50.826992",
"amount": -33000,
"details": {
"method": "CASH"
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:51.983019",
"amount": 30000,
"amountPaid": 30000,
"paymentTime": "2024-08-26T07:30:51.983019",
"details": {
"category": "PREPAID",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "PAYMENT",
"entryTime": "2024-08-26T07:30:51.983019",
"amount": -30000,
"details": {
"method": "CASH"
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:52.327646",
"amount": 1500,
"amountPaid": 0,
"details": {
"category": "FEE",
"description": "Manual Fee",
"waive": false
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "PAYMENT",
"entryTime": "2024-08-26T07:30:52.431402",
"amount": 30000,
"details": {
"method": "CASH"
}
},
{
"bookEntryId": "be_JfNkzV4itfk",
"type": "PAYMENT",
"entryTime": "2024-08-26T07:30:52.43866",
"amount": -30000,
"details": {
"method": "PREPAID"
}
},
{
"bookEntryId": "be_RMhnGWgFSnp",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:53.063417",
"amount": 5000,
"amountPaid": 0,
"details": {
"category": "FEE",
"description": "Test fee",
"waive": false
}
},
{
"bookEntryId": "be_K7egMpsjeEs",
"type": "CHARGE",
"entryTime": "2024-08-26T07:30:54.70939",
"amount": -5000,
"amountPaid": 0,
"details": {
"category": "FEE",
"description": "Test fee",
"waive": true
}
}
]
}
]
}
}
Loads all Account Receivable activity for ledger linked to a lease.
Required Properties
leaseId- the ID of the lease to retrieve the ledger for- or
facilityId- the ID of the facility to retrieve the ledger for
Book entry structure
bookEntryId- the ID of the book entrytype- the type of the entry, which can beCHARGE,PAYMENT,TRANSFER, orWRITE_OFFentryTime- the date and time the entry was madeamount- the amount of the entry in centsamountPaid- the amount of the entry which has been paid in centspaymentTime- the date and time the charge was fully paid, if applicabledetails- an object containing additional details about the entry:- for
CHARGEentries:category- the category of the charge, which can beRENT,COVERAGE,FEE,RETAIL_SALE,DISCOUNT,TAX_STATE,TAX_LOCAL,DAMAGE,AUCTION,PREPAID,CREDIT,DEPOSITorUNKNOWNaccruesOn- the date the charge accrues fromdescription- a description of the chargewaive- a boolean indicating if the charge is a waive
- for
PAYMENTentries:method- the payment method used for the payment, which can bePREPAID,CREDIT,DEPOSIT,CREDIT_CARD,OFFLINE_CARD,CASH,ACH,ACSS,CHECK,E_TRANSFER,MONEY_ORDER,ONLINE_BANKING,VENMO,PAYPAL,ZELLE,CASH_APP,EXTERNALcardType- the type of card used for the paymentcardLastFour- the last 4 digits of the card used for the paymentcheckNumber- the check number used for the payment
- for
TRANSFERentries:source- the source of the transfer, which can beLEASE_BALANCE,IMPORTED_BALANCEorIMPORTED_DEPOSIT
- for
WRITE_OFFentries:explanation- the reason for the write-off
- for
Coverage
- Add private policy info
- Remove private policy info
- Download Private Policy
- Coverage plans
- Coverage Policies Search
- Coverage Enroll
- Coverage Policy Unenroll
Add private policy info
POST /v1/coverage/add-private-policy
Request Body — coverage/add-private-policy
{
"leaseId": "lease_<ID>",
"policyNumber": "123456",
"expirationDate": "2024-06-19",
}
Adds the private coverage policy number and expiration date for a lease.
Required Properties
leaseId- the ID of the lease to set the private policy info forpolicyNumber- the policy number for the private coverage policyexpirationDate- the expiration date for the private coverage policy
Error Conditions
- Lease must not have a private policy number already set
Remove private policy info
POST /v1/coverage/remove-private-policy
Request Body — coverage/remove-private-policy
{
"leaseId": "lease_<ID>"
}
Removes the private coverage policy number and expiration date for a lease.
Download Private Policy
POST /v1/coverage/download-private-policy
Request Body — coverage/download-private-policy
{
"leaseId": "lease_<ID>"
}
Response Headers
Content-Type: application/pdf
Content-Disposition: attachment; filename="private_policy.pdf"
Response Body — coverage/download-private-policy
The response body contains the requested private policy file as a binary stream
Required Properties
leaseId- the ID of the lease to remove the private policy info for
Error Conditions
- Lease must have a private policy number already set
Coverage plans
POST /v1/coverage-levels/search
Request Body — coverage-levels/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp", // Deprecated. Use pricingGroupId
"pricingGroupId": "pg_4a2da7d271a"
},
"expansions": [ "coverageProgram" ]
}
Response Body — coverage-levels/search
{
"status": 200,
"data": {
"coverageLevels": [
{
"coverageLevelId": "covlevel_<ID>",
"coverageProgramId": "covprogram_<ID>",
"provider": "SAFELEASE", // Deprecated. Use provider from the coverageProgram expansion
"policyNumber": "123456", // Deprecated. Use policyNumber from the coverageProgram expansion
"active": true | false,
"default": true | false,
"coverageAmount": 100000,
"premiumAmount": 1500,
"pricingGroupIds": ["pg_4a2da7d271a", "pg_9f13ab77c22"]
},
{ /* ... */ }
],
"coveragePrograms": [
{
"coverageProgramId": "covprogram_<ID>",
"provider": "SAFELEASE",
"policyNumber": "123456",
"coverageOptions": {
"allowTenantOwnInsurance": true,
"hideTenantOwnInsuranceOnStorefront": false,
"allowWaiveInsurance": true,
"hideWaiveInsuranceOnStorefront": false
}
}
]
}
}
Search for coverage levels by pricing group. Coverage is configured per pricing group, so
each coverage level is returned once with pricingGroupIds listing every pricing group it applies to.
Filtering by facilityId is deprecated but still supported; it returns the union of coverage levels
across all of the facility's pricing groups.
Each coverage level belongs to a coverage program, identified by coverageProgramId. Request the
coverageProgram expansion to also receive the program object(s) — returned as the coveragePrograms
array — which carry the program-wide coverageOptions.
Required Properties
Exactly one of the following must be provided:
pricingGroupId- limits results to coverage levels of a particular pricing groupfacilityId- Deprecated. UsepricingGroupId. Limits results to coverage levels across all pricing groups in a particular facility
Response Properties
pricingGroupIds- the pricing groups this coverage level is available in
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; the only supported value for this endpoint iscoverageProgram
Response Parameters
coverageProgramId- the ID of the coverage program this level belongs to; use it to associate a level with an entry in thecoverageProgramsexpansiondefault- whether this coverage level is the program's default (the level preselected on Cubby storefronts)provider/policyNumber- the coverage provider and policy number. These are attributes of the coverage program and are duplicated onto each level for convenience so they remain available when thecoverageProgramexpansion is not requested. ThecoverageProgramobject is the source of truth; the level-level copies may be removed in a future major version.
Expansions
coverageProgram- returns the distinct coverage program(s) for the matched levels as thecoverageProgramsarray. Join each level to its program viacoverageProgramId. Each program entry carries:coverageProgramId- the program ID (join key withcoverageLevel.coverageProgramId)provider- the coverage providerpolicyNumber- the program's policy numbercoverageOptions- the program's additional options governing the coverage step:allowTenantOwnInsurance- tenants may use their own insurance coverage (with proof of insurance)hideTenantOwnInsuranceOnStorefront- hide the own-insurance option from online bookingallowWaiveInsurance- tenants may opt out of coveragehideWaiveInsuranceOnStorefront- hide the opt-out option from online booking
Coverage Policies Search
POST /v1/coverage/search
Request Body — coverage/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"leaseId": "lease_V4w64pjUwVK",
"activeOnOrAfter": "2024-03-01",
"activeOnOrBefore": "2024-10-31"
}
}
Response Body — coverage/search
{
"status": 200,
"data": {
"coverages": [
{
"leaseId": "lease_V4w64pjUwVK",
"facilityId": "fac_C7bSZyPT6fp",
"startDate": "2024-05-01",
"endDate": "2024-07-01",
"coverageAmount": 100000,
"premiumAmount": 1500
},
{/* ... */}
]
}
}
Required Properties
facilityId- limits results to policies in a particular facility- or
leaseId- limit results to policies for a particular lease
Optional Properties
activeOnOrAfter- limits results to policies which are active on or after a specific dateactiveOnOrBefore- limits results to policies which are active on or before a specific date
Coverage Enroll
POST /v1/coverage/enroll
Request Body — coverage/enroll
{
"lease": "lease_<ID>",
"coverageLevelId": "covlevel_<ID>",
"immediate": true | false
}
If immediate is true, immediately enrolls a lease at the specified coverage level. Charges to the next rent date are
automatically prorated. Any coverage which is already paid for is cancelled, with the unused portion credited to the
account.
If immediate is false, changes will take effect on the next rent date.
Error Conditions
- Only leases which are active and in good standing can be enrolled
- Only leases where the
coverageAutoenrollableistruemay be enrolled
Coverage Policy Unenroll
POST /v1/coverage/unenroll
Request Body — coverage/unenroll
{
"lease": "lease_<ID>",
"immediate": true | false
}
If immediate is true, immediately unenrolls a lease from coverage. Any coverage which is already paid for is cancelled,
with the unused portion credited to the account.
If immediate is false, changes will take effect on the next rent date.
Error Conditions
- Only leases which are active and have a coverage policy may be unenrolled
Payments
Payments Search
POST /v1/payments/search
Request Body — payments/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"customerId": "cust_BqaN6zApXCH",
"paymentDateOnOrAfter": "2024-03-01",
"paymentDateOnOrBefore": "2024-03-31"
}
}
Response Body — payments/search
{
"status": 200,
"data": {
"payments": [
{
"paymentId": "payment_V4w64pjUwVK",
"createdAt": "2024-03-01T12:00:00",
"amount": 1500,
"customerId": "cust_BqaN6zApXCH",
"methodType": "CREDIT_CARD" | "ACH" | "ACSS" | "CASH" | "CASH_APP" | "CHECK" | "E_TRANSFER" | "MONEY_ORDER" | "OFFLINE_CARD" | "ONLINE_BANKING" | "PAYPAL" | "VENMO" | "ZELLE"
"status": "SUCCEEDED" | "DECLINED" | "REJECTED" | "FAILED" | "REFUND_INITIATED" | "REFUNDED" | "DISPUTED" | "DIRECT_DEBIT_RETURN" | "PENDING",
"reason": "Insufficient funds",
"explanation": "The account did not have sufficient funds to cover the transaction amount."
},
{/* ... */}
]
}
}
Search for payments by facility, customer, or payment date
Required Properties
facilityId- limits results to payments in a particular facility- or
customerId- limits results to payments for a particular customer
Optional Properties
paymentDateOnOrAfter- limits results to payments which were made on or after a specific datepaymentDateOnOrBefore- limits results to payments which were made on or before a specific date
Auctions
Auctions Search
POST /v1/auctions/search
Request Body — auctions/search
{
"where": {
"auctionId": "auction_V4w64pjUwVK",
"facilityId": "fac_C7bSZyPT6fp"
},
"expansions": [ "winningBidders", "leases", "units" ]
}
Response Body — auctions/search
{
"status": 200,
"data": {
"auctions": [
{
"auctionId": "auction_V4w64pjUwVK",
"auctionTime": "2024-03-01T12:00:00",
"advertisementDeadline": "2024-02-01T12:00:00",
"leaseConfigurationId": "lc_4a2da7d271a",
"auctionedLeases": [
{
"leaseId": "lease_V4w64pjUwVK",
"unitId": "unit_GfNkzV4itfk",
"lienStartDate": "2024-03-01",
"status": "LISTED" | "NO_BIDS" | "SOLD" | "PAYMENT_RECEIVED" | "COMPLETE" | "CANCELLED",
"winningBidderId": "cust_BqaN6zApXCH",
"bidAmount": 10000,
"depositAmount": 5000
}
]
},
{/* ... */}
],
"winningBidders": [
{
"customerId": "cust_BqaN6zApXCH",
"name": "John Smith",
"firstName": "John",
"lastName": "Smith",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "john.smith@example.org",
"phone": "+15943590263"
}
}
],
"leases": [ ... ],
"units": [ ... ]
}
}
Search for auctions by facility or auction ID
Required Properties
facilityId- limits results to auctions in a particular facility- or
auctionId- limits results to a specific auction
Supported expansions:
winningBidders- includes information about the winning bidders for each auctioned leaseleases- includes information about the leases being auctionedunits- includes information about the units being auctioned
Response Parameters
auctionId- the ID of the auctionauctionTime- the date and time of the auctionadvertisementDeadline- the deadline for publishing ad for the auctionleaseConfigurationId- the ID of the lease configuration associated with the auctionauctionedLeases- an array of leases which are being auctioned-
leaseId- the ID of the lease
-
lienStartDate- the date the lien started
-
status- the status of the auction, which can be one of the following:LISTED- the lease is listed for auctionNO_BIDS- the lease did not receive any bidsSOLD- the lease was soldPAYMENT_RECEIVED- the winning bidder has successfully paidCOMPLETE- the auction is completeCANCELLED- the auction process was cancelled
-
winningBidderId- the ID of the winning bidder (which is a ID of acustomerentity)
-
bidAmount- the amount of the winning bid
-
depositAmount- the amount of the deposit charged to the winning bidder
Auction Create
POST /v1/auctions/create
Request Body — auctions/create
{
"facilityId": "fac_C7bSZyPT6fp",
"auctionTime": "2024-03-01T12:00:00",
"leaseConfigurationId": "lc_4a2da7d271a"
}
Response Body — auctions/create
{
"status": 200,
"data": {
"auctionId": "auction_V4w64pjUwVK"
}
}
Creates a new auction for a facility
Required Properties
facilityId- the ID of the facility to create the auction forauctionTime- the date and time of the auctionleaseConfigurationId- the ID of the lease configuration to use for the auction
Start lien process
POST /v1/auctions/start-lien
Request Body — auctions/start-lien
{
"leaseId": "lease_V4w64pjUwVK",
"auctionId": "auction_V4w64pjUwVK",
"sendEmailAndSms": true | false,
"sendToAlternativeContacts": true | false
}
Starts the lien process for a lease, which may include sending lien notices to the tenant and alternative contacts
Required Properties
leaseId- the ID of the lease to start the lien process forauctionId- the ID of the auction to include the lease in
Optional Properties
sendEmailAndSms- a boolean indicating if email and SMS notices should be sent, defaults tofalsesendToAlternativeContacts- a boolean indicating if alternative contacts should be notified, defaults tofalse
Cancel lien process
POST /v1/auctions/cancel-lien
Request Body — auctions/cancel-lien
{
"leaseId": "lease_V4w64pjUwVK"
}
Cancels the lien process for a lease which is in lien process but has not yet been settled and/or paid for
Notes
Notes Search
POST /v1/notes/search
Request Body — notes/search
{
"where": {
"leaseId": "lease_V4w64pjUwVK",
"customerId": "cust_BqaN6zApXCH",
"leadId": "lead_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"pricingGroupId": "pg_4a2da7d271a",
}
}
Response Body — notes/search
{
"status": 200,
"data": {
"notes": [
{
"text": "Customer requested a larger unit",
"createdAt": "2024-03-01T12:00:00.000000Z",
"createdBy": "user_4a2da7d271a"
}
]
}
}
Search for notes related to leases, customers, leads, units, or pricing groups.
Required Properties
leaseId- limits results to notes for a specific lease- or
customerId- limits results to notes for a specific customer- or
leadId- limits results to notes for a specific lead- or
unitId- limits results to notes for a specific unit- or
pricingGroupId- limits results to notes for a specific pricing group
Response Properties
text- the text of the notecreatedAt- the date and time the note was created, as an ISO-8601 UTC timestamp (e.g.2024-03-01T12:00:00.000000Z)createdBy- the ID of the user who created the note
Notes Create
POST /v1/notes/create
Request Body — notes/create
{
"text": "Customer requested a larger unit",
"leaseId": "lease_V4w64pjUwVK",
"customerId": "cust_BqaN6zApXCH",
"leadId": "lead_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"pricingGroupId": "pg_4a2da7d271a"
}
Creates a new note related to a lease, customer, lead, unit, or pricing group.
Required Properties
text- the text of the note- and one of
leaseId- the ID of the lease to attach the note to- or
customerId- the ID of the customer to attach the note to- or
leadId- the ID of the lead to attach the note to- or
unitId- the ID of the unit to attach the note to- or
pricingGroupId- the ID of the pricing group to attach the note to
Tasks
Tasks Search
POST /v1/tasks/search
Request Body — tasks/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"unitId": "unit_GfNkzV4itfk",
"customerId": "cust_BqaN6zApXCH",
"status": "OPEN",
"due": true
},
"expansions": ["facility", "unit", "tenant"]
}
Response Body — tasks/search
{
"status": 200,
"data": {
"tasks": [
{
"id": "task_V4w64pjUwVK",
"title": "Inspect unit for damage",
"description": "Check for water damage after recent storm",
"dueDate": "2026-03-01",
"status": "OPEN",
"facilityId": "fac_C7bSZyPT6fp",
"customerId": "cust_BqaN6zApXCH",
"unitId": "unit_GfNkzV4itfk"
},
{/* ... */}
],
"facilities": [
{/* ... */}
],
"units": [
{/* ... */}
],
"customers": [
{/* ... */}
]
}
}
Search for tasks by facility, organization, unit, customer, status, or due date
Required Properties
At least one of the following:
organizationId- limits results to tasks in a specific organizationfacilityId- limits results to tasks in a specific facilityunitId- limits results to tasks for a specific unitcustomerId- limits results to tasks for a specific customer
Optional Properties
status- filters tasks by status; one ofOPEN,COMPLETED, orARCHIVEDdue- whentrue, filters to overdue tasks onlyexpansions- an array of strings which can be used to include additional data in the response; supported for this endpoint arefacility,unit, andtenant
Tasks Create
POST /v1/tasks/create
Request Body — tasks/create
{
"facilityId": "fac_C7bSZyPT6fp",
"title": "Inspect unit for damage",
"description": "Check for water damage after recent storm",
"dueDate": "2026-03-01",
"customerId": "cust_BqaN6zApXCH",
"unitId": "unit_GfNkzV4itfk",
"assignedManagerIds": ["user_4a2da7d271a"]
}
Creates a new task at the specified facility
Required Properties
facilityId- the ID of the facility to create the task intitle- the title of the task
Optional Properties
description- a description of the taskdueDate- the due date of the task (YYYY-MM-DD)customerId- the ID of the customer to associate the task withunitId- the ID of the unit to associate the task withassignedManagerIds- an array of manager IDs to assign the task to
Reports
- General Ledger Cash Based Report
- General Ledger Accrual Based Report
- Aged Receivables Report
- Rent Roll Report
- Merchant Services Disbursements Report
General Ledger Cash Based Report
POST /v1/reports/general-ledger/cash
Request Body — reports/general-ledger/cash
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"startDate": "2024-01-01",
"reportRelativeDuration": "M"
}
}
Response Body — reports/general-ledger/cash
{
"status": 200,
"data": {
"entries": [
{
"id": "je_F7N3jm5F1MU.be_BRGbhSRYecW",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:45:45.725995",
"amount": 10000,
"direction": "CREDIT",
"account": "PREPAID_RENT",
"details": {
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_CmkcJ6Gq16a",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:45:45.715093",
"amount": 10000,
"direction": "DEBIT",
"account": "DEPOSIT",
"details": {
"description": "Security Deposit",
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_FAK3KdKWWqw",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:43:02.588516",
"amount": 25031,
"direction": "DEBIT",
"account": "CREDIT_CARD_PAYMENTS",
"details": {
"cardType": "visa",
"cardLastFour": "1111",
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_LDPdoUPucz8",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:42:27.975048",
"amount": 14100,
"direction": "CREDIT",
"account": "RENT",
"details": {
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_VPKcAEmitNk",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:42:27.975048",
"amount": 282,
"direction": "CREDIT",
"account": "TAX_STATE",
"details": {
"description": "2%",
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_WLEM365sWGg",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:42:27.975048",
"amount": 649,
"direction": "CREDIT",
"account": "TAX_LOCAL",
"details": {
"description": "4.6%",
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
},
{
"id": "je_F7N3jm5F1MU.be_NM4tPTmWjcK",
"journalEntryId": "je_F7N3jm5F1MU",
"paymentTime": "2025-08-22T04:43:02.56492",
"entryTime": "2025-08-22T04:42:27.975048",
"amount": 10000,
"direction": "CREDIT",
"account": "DEPOSIT",
"details": {
"customerId": "cust_FH1Hw36xoLd",
"customerName": "John Smith",
"unitName": "A-100",
"pricingGroupId": "pg_LnKY1qJHmc6"
}
}
]
}
}
Generates a cash basis general ledger report for a facility over a specified time period.
Required Properties
facilityId- the ID of the facility to generate the report forstartDate- the start date for the report inYYYY-MM-DDformatreportRelativeDuration- the duration of the report relative to the start date. Valid values are:D- one dayM- one month
Response Parameters
The response contains an array of journal entries, each of which contains the following fields:
id- the ID of the journal entry line itemjournalEntryId- the ID of the journal entrypaymentTime- the date and time the payment was madeentryTime- the date and time the journal entry was createdamount- the amount of the journal entry in centsdirection- the direction of the journal entry, which can beDEBITorCREDITaccount- the account the journal entry is associated with, which can be one of the following:-
ACCOUNT_RECEIVABLE- Accounts Receivable
-
RENT- Rent
-
INSURANCE- Insurance
-
FEES- Fees
-
DISCOUNTS- Discounts
-
TAX_STATE- State Tax
-
TAX_LOCAL- Local Tax
-
PREPAID_RENT- Prepaid
-
CREDIT_CARD_PAYMENTS- Credit Card
-
OFFLINE_CARD_PAYMENTS- Offline Card
-
CASH_PAYMENTS- Cash
-
ACH_PAYMENTS- ACH
-
ACSS_PAYMENTS- ACSS
-
CHECK_PAYMENTS- Check
-
MONEYORDER_PAYMENTS- Money Order
-
VENMO_PAYMENTS- Venmo
-
PAYPAL_PAYMENTS- PayPal
-
ZELLE_PAYMENTS- Zelle
-
CASH_APP_PAYMENTS- Cash App
-
E_TRANSFER_PAYMENTS- E-Transfer
-
ONLINE_BANKING_PAYMENTS- Online Banking
-
DEPOSIT- Deposit
-
OLD_SYSTEM- Imported Balance
-
OLD_SYSTEM_DEPOSIT- Imported Deposit
-
DAMAGE- Damage
-
RETAINED_DEPOSIT- Retained Deposit
-
BAD_DEBT- Bad Debt
-
GIVEN_CREDITS- Given Credits
-
CREDITS- Credits
-
USED_CREDITS- Used Credits
-
EXTERNAL_ACCOUNT- External Account
-
WAIVED_FEES- Waived Fees
-
WAIVED_DAMAGE- Waived Damage
-
WAIVED_RENT- Waived Rent
-
AUCTION- Auctions
-
EXTERNAL_AUCTION- External Auction
-
ACCOUNTS_PAYABLE- Accounts Payable
-
RETAIL_SALES- Retail Sales
mappedGlAccount- the mapped GL account for the journal entry, if such a mapping exists for the facilitymappedGlAccountNumber- the mapped GL account number for the journal entry, if such a mapping exists for the facilitydetails- an object containing additional details about the journal entry:-
description- a description of the journal entry
-
customerId- the ID of the customer associated with the journal entry
-
customerName- the name of the customer associated with the journal entry
-
unitName- the name of the unit associated with the journal entry
-
cardType- the type of card used for the payment, if applicable
-
cardLastFour- the last four digits of the card used for the payment, if applicable
-
checkNumber- the check number used for the payment, if applicable
-
pricingGroupId- the ID of the pricing group associated with the journal entry
-
coverageLevelId- the ID of the coverage level associated with the journal entry, if applicable
-
feeId- the ID of the fee associated with the journal entry, if applicable
General Ledger Accrual Based Report
POST /v1/reports/general-ledger/accrual
Request Body — reports/general-ledger/accrual
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"startDate": "2024-01-01",
"reportRelativeDuration": "M"
}
}
Response Body — reports/general-ledger/accrual
{
"status": 200,
"data": {
"entries": [
{
"id": "be_NBN5vzcHBv5",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"account": "FEES",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "FEE_NON_TAXABLE",
"explanation": "Move-In Fee $25.0",
"debit": 0,
"credit": 2500
},
{
"id": "be_PSwhQQa9UVC",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"account": "ACCOUNT_RECEIVABLE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "FEE_NON_TAXABLE",
"explanation": "Move-In Fee $25.0",
"debit": 2500,
"credit": 0
},
{
"id": "be_Pjn1cAekzuA",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"account": "DEPOSIT",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "DEPOSIT",
"explanation": "Security Deposit",
"debit": 0,
"credit": 20000
},
{
"id": "be_Rqop5WxWs4L",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"account": "ACCOUNT_RECEIVABLE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "DEPOSIT",
"explanation": "Security Deposit",
"debit": 20000,
"credit": 0
},
{
"id": "be_FWuEeHyLSz6",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "RENT",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "Rent",
"debit": 0,
"credit": 12500
},
{
"id": "be_AkGodRDQcfo",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "ACCOUNT_RECEIVABLE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "Rent",
"debit": 12500,
"credit": 0
},
{
"id": "be_GHQvBnczPcK",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "TAX_STATE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "4.5%",
"debit": 0,
"credit": 563
},
{
"id": "be_NRD5PG38VXi",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "ACCOUNT_RECEIVABLE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "4.5%",
"debit": 563,
"credit": 0
},
{
"id": "be_BZyw4u5k3Qi",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "TAX_LOCAL",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "0.5%",
"debit": 0,
"credit": 63
},
{
"id": "be_KF1TCs8NTPz",
"journalEntryId": "je_Md6kbRese5r",
"entryTime": "2024-01-01T00:00:00",
"facilityId": "fac_JPzPkHHhPcP",
"facilityName": "Test Facility",
"customerId": "cust_JZQa2bFkpvW",
"customerName": "John Smith",
"unitId": "unit_G77Ba9sR8Cr",
"unitName": "IPFN723",
"accruesOn": "2024-01-01",
"accruesThrough": "2024-01-31",
"account": "ACCOUNT_RECEIVABLE",
"mappedGlAccount": "",
"mappedGlAccountNumber": "",
"taxExempt": false,
"taxCategory": "RENT_ENCLOSED_STORAGE",
"explanation": "0.5%",
"debit": 63,
"credit": 0
}
]
}
}
Generates an accrual basis general ledger report for a facility over a specified time period.
Required Properties
facilityId- the ID of the facility to generate the report forstartDate- the start date for the report inYYYY-MM-DDformatreportRelativeDuration- the duration of the report relative to the start date. Valid values are:D- one dayM- one month
Response Parameters
The response contains an array of journal entry line items, each of which contains the following fields:
id- the ID of the journal entry line itemjournalEntryId- the ID of the journal entryentryTime- the date and time the journal entry was createdfacilityId- the ID of the facility associated with the journal entryfacilityName- the name of the facility associated with the journal entrycustomerId- the ID of the customer associated with the journal entrycustomerName- the name of the customer associated with the journal entryunitId- the ID of the unit associated with the journal entryunitName- the name of the unit associated with the journal entryaccount- the account the journal entry is associated with, which can be one of the following:-
ACCOUNT_RECEIVABLE- Accounts Receivable
-
RENT- Rent
-
INSURANCE- Insurance
-
FEES- Fees
-
DISCOUNTS- Discounts
-
TAX_STATE- State Tax
-
TAX_LOCAL- Local Tax
-
PREPAID_RENT- Prepaid
-
CREDIT_CARD_PAYMENTS- Credit Card
-
OFFLINE_CARD_PAYMENTS- Offline Card
-
CASH_PAYMENTS- Cash
-
ACH_PAYMENTS- ACH
-
ACSS_PAYMENTS- ACSS
-
CHECK_PAYMENTS- Check
-
MONEYORDER_PAYMENTS- Money Order
-
VENMO_PAYMENTS- Venmo
-
PAYPAL_PAYMENTS- PayPal
-
ZELLE_PAYMENTS- Zelle
-
CASH_APP_PAYMENTS- Cash App
-
E_TRANSFER_PAYMENTS- E-Transfer
-
ONLINE_BANKING_PAYMENTS- Online Banking
-
DEPOSIT- Deposit
-
OLD_SYSTEM- Imported Balance
-
OLD_SYSTEM_DEPOSIT- Imported Deposit
-
DAMAGE- Damage
-
RETAINED_DEPOSIT- Retained Deposit
-
BAD_DEBT- Bad Debt
-
GIVEN_CREDITS- Given Credits
-
CREDITS- Credits
-
USED_CREDITS- Used Credits
-
EXTERNAL_ACCOUNT- External Account
-
WAIVED_FEES- Waived Fees
-
WAIVED_DAMAGE- Waived Damage
-
WAIVED_RENT- Waived Rent
-
AUCTION- Auctions
-
EXTERNAL_AUCTION- External Auction
-
ACCOUNTS_PAYABLE- Accounts Payable
-
RETAIL_SALES- Retail Sales
mappedGlAccount- the mapped GL account for the journal entry, if such a mapping exists for the facilitymappedGlAccountNumber- the mapped GL account number for the journal entry, if such a mapping exists for the facilitytaxExempt- a boolean indicating if the journal entry is tax exempttaxCategory- the tax category for the journal entry, which can be one of the following:-
RENT_ENCLOSED_STORAGE- Rent for enclosed storage
-
RENT_PARKING_SPACE- Rent for parking space
-
RENT_MOBILE_STORAGE- Rent for mobile storage
-
INSURANCE- Insurance
-
FEE_TAXABLE- Taxable fee
-
FEE_NON_TAXABLE- Non-taxable fee
-
RETAIL_GENERAL- General retail
-
RETAIL_FOOD- Food retail
-
RETAIL_NON_TAXABLE- Non-taxable retail
-
DAMAGE- Damage
-
DEPOSIT- Deposit
-
AUCTION- Auction
-
EXTERNAL_AUCTION- External Auction
explanation- a description of the journal entrydebit- the debit amount for the journal entry in centscredit- the credit amount for the journal entry in cents
Aged Receivables Report
POST /v1/reports/aged-receivables
throughDate is optional and defaults to the facility's current date. When provided, aging buckets are computed as of the end of that date.
Request Body — reports/aged-receivables
{
"where": {
"facilityIds": [
"fac_C7bSZyPT6fp"
],
"throughDate": "2024-08-31"
}
}
Response Body — reports/aged-receivables
{
"status": 200,
"data": {
"entries": [
{
"facilityId": "fac_Qi19JvKQBgu",
"facilityName": "Test Facility",
"leaseId": "lease_XQ1zDzcYdfs",
"unitId": "unit_GHrAvzbKK7K",
"unitName": "SZEF563",
"pricingGroupId": "pg_HtikzP9RB3Y",
"pricingGroupName": "5x5 with AC",
"customerId": "cust_P4Cecw1xuQE",
"customerName": "John Smith",
"totalAmount": 48752,
"ranges": [
{
"range": "RANGE_0_30",
"amount": 13126
},
{
"range": "RANGE_30_60",
"amount": 35626
},
{
"range": "RANGE_60_90",
"amount": 0
},
{
"range": "RANGE_90_120",
"amount": 0
},
{
"range": "RANGE_120_PLUS",
"amount": 0
},
{
"range": "RANGE_UNKNOWN",
"amount": 0
}
]
}
]
}
}
Generates an aged receivables report for one or more facilities.
Required Properties
facilityIds- an array of facility IDs to generate the report for
Response Parameters
The response contains an array of aged receivable entries, one for each lease with an outstanding balance, each of which contains the following fields:
facilityId- the ID of the facilityfacilityName- the name of the facilityleaseId- the ID of the leaseunitId- the ID of the unitunitName- the name of the unitpricingGroupId- the ID of the pricing grouppricingGroupName- the name of the pricing groupcustomerId- the ID of the customercustomerName- the name of the customertotalAmount- the total outstanding balance for the lease in centsranges- an array of objects representing the aged receivable ranges, each of which-
range- the range of days past due, which can be one of the following:RANGE_0_30- 0 to 30 days past dueRANGE_30_60- 30 to 60 days past dueRANGE_60_90- 60 to 90 days past dueRANGE_90_120- 90 to 120 days past dueRANGE_120_PLUS- more than 120 days past dueRANGE_UNKNOWN- unknown days past due
-
amount- the amount outstanding in that range in cents
Rent Roll Report
POST /v1/reports/rent-roll
Request Body — reports/rent-roll
{
"where": {
"facilityIds": [
"fac_C7bSZyPT6fp"
],
"throughDate": "2024-08-31"
}
}
Response Body — reports/rent-roll
{
"status": 200,
"data": {
"entries": [
{
"facilityId": "fac_Qi19JvKQBgu",
"facilityName": "Test Facility",
"status": "RENTED",
"unitId": "unit_GHrAvzbKK7K",
"unitName": "SZEF563",
"pricingGroupId": "pg_HtikzP9RB3Y",
"pricingGroupName": "5x5 with AC",
"width": 5.0,
"depth": 5.0,
"height": 8.0,
"standardRate": 5000,
"customerId": "cust_P4Cecw1xuQE",
"customerName": "John Smith",
"companyName": "Acme Corp",
"contact": {
"address": "2055 Earnest Mountain",
"address2": "Apt. 805",
"city": "Johnston",
"state": "Minnesota",
"country": "USA",
"zip": "15219",
"email": "john.smith@example.org"
},
"totalDue": 7500,
"deposit": 5000,
"prepaid": 2000,
"credit": 0,
"monthlyRentalAmount": 6000,
"effectiveRate": 5500,
"rentVarianceAmount": -1000,
"lastRentChangeDate": "2024-03-01",
"rentChangeScheduledDate": "2024-09-01",
"rentChangeNewRentAmount": 6500,
"billingCycle": "MONTHLY",
"moveInDate": "2024-01-15",
"paidOnDate": "2024-07-15",
"paidThroughDate": "2024-08-14",
"billingDayOfMonth": 15,
"taxExempt": false,
"paid": true,
"autoPayEnabled": true,
"autoPayPaymentMethodId": "pm_1GqIC8HYgolSBA35XqL5a2M",
"overlockNeeded": false,
"overlockApplied": false
}
]
}
}
Generates a rent roll report for one or more facilities.
Required Properties
facilityIds- an array of facility IDs to generate the report forthroughDate- the date through which to calculate rent due inYYYY-MM-DDformat
Response Parameters
The response contains an array of rent roll entries, one for each unit, each of which contains the following fields:
facilityId- the ID of the facilityfacilityName- the name of the facilitystatus- the status of the unit, which can be one of the following:RENTED- the unit is currently rentedSCHEDULED_MOVE_IN- the unit has a scheduled move-inVACANT- the unit is vacantUNAVAILABLE- the unit is unavailable for rent
unitId- the ID of the unitunitName- the name of the unitpricingGroupId- the ID of the pricing grouppricingGroupName- the name of the pricing groupwidth- the width of the unit in feetdepth- the depth of the unit in feetheight- the height of the unit in feetstandardRate- the standard rental rate for the unit in centscustomerId- the ID of the customer renting the unitcustomerName- the name of the customer renting the unitcompanyName- the company name of the customer renting the unitcontact- the contact information for the customer renting the unittotalDue- the total amount due for the unit in centsdeposit- the deposit amount for the unit in centsprepaid- the prepaid amount for the unit in centscredit- the credit balance available on the unit's lease in centsmonthlyRentalAmount- the monthly rental amount for the unit in centseffectiveRate- the effective rate for the unit in cents: the net rent (rent less discounts and waived rent) charged for the current billing periodrentVarianceAmount- the variance in rent for the unit in centslastRentChangeDate- the date of the tenant's last completed rent change, or omitted if the rent has never changedrentChangeScheduledDate- the date the rent change is scheduled to take effectrentChangeNewRentAmount- the new rent amount after the change in centsbillingCycle- the billing cycle for the unit, which can be one of the following:WEEKLY- billed weeklyBI_WEEKLY- billed every two weeksDAYS_28- billed every 28 daysMONTHLY- billed monthly
moveInDate- the move-in date for the unitpaidOnDate- the date the unit was last paid onpaidThroughDate- the date through which the unit is paidbillingDayOfMonth- the day of the month the unit is billed ontaxExempt- a boolean indicating if the unit is tax exemptpaid- a boolean indicating if the unit is paidautoPayEnabled- a boolean indicating if auto-pay is enabled for the unitoverlockNeeded- a boolean indicating if an overlock is needed for the unitoverlockApplied- a boolean indicating if an overlock has been applied to the unit
Not applicable fields might be omitted or set to null.
Merchant Services Disbursements Report
POST /v1/reports/merchant-services-disbursements
Request Body — reports/merchant-services-disbursements
{
"where": {
"facilityIds": [
"fac_C7bSZyPT6fp"
],
"startDate": "2024-08-01",
"reportRelativeDuration": "M"
}
}
Response Body — reports/merchant-services-disbursements
{
"status": 200,
"data": {
"batches": [
{
"facilityId": "fac_C7bSZyPT6fp",
"facilityName": "Test Facility",
"paymentProvider": "STRIPE",
"merchantId": "acct_1234567890",
"batchDate": "2024-08-15",
"batchNumber": "po_1ABC2DEF3GHI",
"batchStatus": "paid",
"methodType": "card",
"amount": 1250
}
],
"transactions": [
{
"facilityId": "fac_C7bSZyPT6fp",
"facilityName": "Test Facility",
"paymentProvider": "STRIPE",
"batchNumber": "po_1ABC2DEF3GHI",
"batchDate": "2024-08-15",
"paymentId": "pay_Ab3xK9mR2wq",
"transactionId": "txn_9876543210",
"date": "2024-08-14",
"amount": 1250,
"status": "APPROVED",
"type": "SALE",
"customerId": "con_7dF2kL9pQx",
"customerName": "John Smith",
"methodType": "CREDIT_CARD",
"cardBrand": "VISA",
"lastFour": "1234"
}
]
}
}
Generates a merchant services disbursements report for one or more facilities over a specified time period. The report includes batch-level settlement summaries and individual transaction details from configured payment providers (Stripe, Payabli).
Required Properties
facilityIds- an array of facility IDs to generate the report forstartDate- the start date for the report inYYYY-MM-DDformatreportRelativeDuration- the duration of the report relative to the start date. Valid values are:D- one dayM- one month
Response Parameters
The response contains two arrays: batches and transactions. Fields that are not applicable are omitted from the response.
Batches
Each batch entry represents a settlement batch from a payment provider:
facilityId- the ID of the facilityfacilityName- the name of the facilitypaymentProvider- the payment provider:STRIPEorPAYABLImerchantId- the merchant account ID with the payment providerbatchDate- the date of the batch inYYYY-MM-DDformatbatchNumber- the batch or payout identifierbatchStatus- the status of the batch. Values depend on the payment provider:- Stripe:
paid,pending,in_transit,canceled,failed - Payabli:
OPEN,CLOSED,TRANSFERRED,FUNDED,RESOLVED,HELD
- Stripe:
methodType- the payment method type for the batch. Values depend on the payment provider:- Stripe:
card,fpx,bank_account - Payabli:
card,ach,wallet,combine
- Stripe:
amount- the total batch amount in cents
Transactions
Each transaction entry represents an individual payment within a batch:
facilityId- the ID of the facilityfacilityName- the name of the facilitypaymentProvider- the payment provider:STRIPEorPAYABLIbatchNumber- the batch or payout identifier this transaction belongs tobatchDate- the date of the parent batch inYYYY-MM-DDformatpaymentId- the Cubby payment identifiertransactionId- the payment provider's transaction identifierdate- the date of the transaction inYYYY-MM-DDformatamount- the transaction amount in centspayabliStatus- (Payabli only) the transaction status as reported by Payabli:AUTHORIZED,APPROVED,DECLINED_BY_PROCESSOR,DECLINED_BY_TECHNICAL_ERROR,VOIDED,FAILED,INITIATEDstatus- the transaction status in Cubby:NEW,INITIATED,PENDING,APPROVED,DECLINED,ERROR,FAILED,VOIDED,CANCELING,VOIDING,APPROVINGtype- the type of transaction:SALE,REFUND,FAILUREcustomerId- the ID of the customer associated with the transactioncustomerName- the name of the customer associated with the transactionmethodType- the payment method used:CREDIT_CARD,ACH,ACSS,CASH,CASH_APP,CHECK,E_TRANSFER, etc.cardBrand- the card brand, if applicable:VISA,MASTERCARD,AMERICAN_EXPRESS,DISCOVER,JCB,UNIONPAY, etc.lastFour- the last four digits of the card or account number, if applicablecheckNo- the check number, if the payment was made by check
Storefront
Storefront Facilities Search
POST /v1/storefront/facilities/search
Request Body — storefront/facilities/search
{
"where": {
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a"
},
"expansions": ["organization", "schedules"]
}
Response Body — storefront/facilities/search
{
"status": 200,
"data": {
"facilities": [
{
"facilityId": "fac_C7bSZyPT6fp",
"organizationId": "org_4a2da7d271a",
"name": "315 Anisha Estates",
"description": "Climate-controlled self storage in downtown.",
"slug": "anisha-estates",
"apiKey": "b73c7e4d-81f2-49e3-bbca-9a6fbd321d56",
"contact": {
"address": "315 Anisha Estates",
"address2": "",
"city": "Thompsonview",
"state": "Alaska",
"country": "USA",
"zip": "98748",
"email": "",
"phone": ""
},
"latitude": "37.774929",
"longitude": "-122.419418",
"schedules": [{/* ... */}]
},
{/* ... */}
],
"organizations": [
{
"organizationId": "org_4a2da7d271a",
"name": "Anisha Estates"
},
{/* ... */}
]
}
}
Search for storefront-visible facilities by facility or organization
Required Properties
facilityId- limits results to a specific facility- or
organizationId- limits results to facilities in a specific organization
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint areorganizationandschedules
Storefront Pricing Groups Search
POST /v1/storefront/pricing-groups/search
Request Body — storefront/pricing-groups/search
{
"where": {
"pricingGroupId": "pg_4a2da7d271a",
"facilityId": "fac_C7bSZyPT6fp"
},
"expansions": ["discounts"]
}
Response Body — storefront/pricing-groups/search
{
"status": 200,
"data": {
"pricingGroups": [
{
"pricingGroupId": "pg_4a2da7d271a",
"name": "Standard",
"description": "10x20 climate-controlled",
"priceDescription": "$220/mo",
"width": 10,
"depth": 20,
"height": 8,
"price": 22000,
"strikethroughPrice": 25000,
"images": ["https://example.com/unit.jpg"],
"features": ["Climate controlled", "Ground floor"],
"discounts": ["discount_JgNkzV4itfk"],
"parking": false,
"vehicleStorage": false
},
{/* ... */}
],
"discounts": [
{
"discountId": "discount_JgNkzV4itfk",
"name": "First Month Free",
"type": "PERPETUAL | PERIODIC | PAID_UPFRONT | ONE_TIME",
"status": "PUBLISHED | ARCHIVED"
},
{/* ... */}
]
}
}
Search for storefront-visible pricing groups by facility or pricing group ID
Required Properties
pricingGroupId- limits results to a specific pricing group- or
facilityId- limits results to pricing groups in a particular facility
Optional Properties
expansions- an array of strings which can be used to include additional data in the response; supported for this endpoint arediscounts
Response Parameters
price- the price in cents (integer)strikethroughPrice- the original/comparison price in cents (integer)width,depth,height- unit dimensionsimages- an array of image URLsfeatures- an array of feature descriptionsdiscounts- an array of discount IDs (expand withdiscountsexpansion to get full discount objects)parking- a boolean indicating if this is a parking spacevehicleStorage- a boolean indicating if this is vehicle storage
Messages
Send SMS
POST /v1/messages/sms/send
Request Body — messages/sms/send
{
"customerId": "cust_BqaN6zApXCH",
"facilityId": "fac_C7bSZyPT6fp",
"body": "Your payment is due tomorrow."
}
Sends an SMS message to a customer
Required Properties
customerId- the ID of the customer to send the message tofacilityId- the ID of the facility to send the message frombody- the body of the message to send (must be at most 320 characters)
Send Email
POST /v1/messages/email/send
Sends an email message to a customer. Unlike the other endpoints in this API, this one is sent as multipart/form-data so that file attachments can be included alongside the JSON request.
The request must include the following parts:
| Part name | Content | Required |
|---|---|---|
request |
A JSON object with the fields described under Required Properties below. The part must be sent with Content-Type: application/json. |
Yes |
attachments |
A file to attach to the email. Repeat the part name for multiple attachments. Maximum of 5 attachments, each up to 5 MB. | No |
JSON body of the
requestpart
{
"customerId": "cust_BqaN6zApXCH",
"facilityId": "fac_C7bSZyPT6fp",
"subject": "Payment Due Reminder",
"body": "<p>Your payment is due tomorrow.</p>"
}
Example: send an email with no attachments
curl -X POST 'https://api.cubbystorage.com/v1/messages/email/send' \
--header 'Authorization: Bearer b73c7e4d-81f2-49e3-bbca-9a6fbd321d56' \
--form 'request={
"customerId": "cust_BqaN6zApXCH",
"facilityId": "fac_C7bSZyPT6fp",
"subject": "Payment Due Reminder",
"body": "<p>Your payment is due tomorrow.</p>"
};type=application/json'
Example: send an email with two attachments
curl -X POST 'https://api.cubbystorage.com/v1/messages/email/send' \
--header 'Authorization: Bearer b73c7e4d-81f2-49e3-bbca-9a6fbd321d56' \
--form 'request={
"customerId": "cust_BqaN6zApXCH",
"facilityId": "fac_C7bSZyPT6fp",
"subject": "Payment Due Reminder",
"body": "<p>Your payment is due tomorrow.</p>"
};type=application/json' \
--form 'attachments=@invoice.pdf' \
--form 'attachments=@receipt.pdf'
Required Properties
The following fields belong inside the JSON request part:
customerId- the ID of the customer to send the message tofacilityId- the ID of the facility to send the message fromsubject- the subject of the email (must be at most 255 characters)body- the body of the email to send (must be at most 256 KB (262,144 characters) long)
Checkout
Checkout Component
The Cubby Checkout is an embeddable web component that provides a complete checkout flow
for your storefront. It can be embedded on any page by including the storefront components
script and placing the <cubby-checkout> element in your HTML.
Setup
Include the Script
<script
type="module"
src="https://cdn.cubbystorage.com/components/latest"
data-api-key="your-storefront-api-key">
</script>
Include the storefront components script on your page. The API key is passed via the
data-api-key attribute on the script tag. This is the same API key used for the
Storefront API endpoints above.
Usage
Basic Checkout
<cubby-checkout
pricing-groups="pg_4a2da7d271a">
</cubby-checkout>
Pre-populated Customer Data
<cubby-checkout
pricing-groups="pg_4a2da7d271a"
customer-name="Jane Smith"
customer-email="jane@example.com"
customer-phone="+15551234567">
</cubby-checkout>
Place the <cubby-checkout> element wherever the checkout flow should appear. The pricing-groups
attribute is required and accepts a single pricing group ID as returned by
the Storefront Pricing Groups Search endpoint. Only one pricing group is supported at this time.
Attributes
| Attribute | Type | Required | Description |
|---|---|---|---|
| pricing-groups | string | Yes | The ID of the pricing group to display |
| customer-name | string | No | Pre-populates the customer name field |
| customer-email | string | No | Pre-populates the customer email field |
| customer-phone | string | No | Pre-populates the customer phone field |