---
name: barebonespm
description: Manage rental properties and the financial ledger in BareBones PM — log rent and expenses, look up what was spent on a property, and produce income/expense summaries for a period or tax year. Use whenever the user asks about their rentals, tenants, units, leases, landlord bookkeeping, Schedule E categories, or says "my properties" / "my ledger" / "my rentals".
license: MIT
---

# BareBones PM

Lightweight property management + financial ledger for DIY landlords. This skill lets you read and
update the user's real data over their account's API.

## Setup — do this first, once

You need two things. Ask the user for whichever is missing; do not guess either.

1. **Base URL** — `https://barebonespm.com` unless the user is self-hosting.
2. **API key** — the user creates one at `https://barebonespm.com/dashboard/api-keys`. It is shown
   **once**, at creation. Every request sends it as `Authorization: Bearer <key>`.

Treat the key as a secret: never print it, never write it into a file the user did not ask for, and
never include it in a URL or a code block you show back to them.

## Discover the API — always, before your first call

**Fetch `{BASE_URL}/api/v1/openapi.json` and work from that.** It is generated from the same
validation schemas the server enforces, and it lists **only** the endpoints currently enabled on
this account's plan. It is therefore always correct and always current.

Do **not** work from a memorised endpoint list, including any list in this file. If an operation
isn't in that document, it is not available — say so rather than guessing at a URL.

Human-readable version of the same thing: `{BASE_URL}/docs`.

## What you can generally do

Properties, units, tenants and leases: create, list, update. Ledger: create and list entries, plus
period summaries. Exact paths, fields and which are enabled live in the OpenAPI document above.

Anything destructive — deleting a property, tenant, unit, lease or ledger entry — is **off by
default** on this API. If a user asks you to delete something and the operation isn't in the
OpenAPI document, tell them to do it in the web app rather than looking for another route. Do not
attempt a delete you had to guess the URL for.

## The ledger — the part with sharp edges

The ledger write endpoint predates the rest of the API and keeps its own contract. Check the
OpenAPI document for the authoritative shape, but these are the things that catch people out:

- **It is `snake_case`**, unlike the rest of the API — both what you send and what you read back:
  `transaction_date`, `property_id`, `unit_id`, `reason_description`, `external_id`, `created_at`.
- **`type`** is `INCOME`, `EXPENSE` or `CHARGE`. An `INCOME` entry is money already received, so it
  is always recorded as paid regardless of what you send for `status`.
- **`category`** is a fixed list mirroring IRS Schedule E lines, so a year's ledger maps 1:1 onto
  the tax form. Read the allowed values from the OpenAPI document and pick the closest one — never
  invent a category. If nothing fits, use `OTHER` and put the detail in `reason_description`.
- **`transaction_date`** is `YYYY-MM-DD`. It defaults to today if omitted, which is usually **not**
  what the user meant — a receipt they are entering now is dated when they paid it. Ask if unclear.
- **`amount`** is a plain number. Send the positive amount and let `type` carry the direction; do
  not negate an expense.
- **`external_id`** makes a write idempotent. Send one whenever you might retry — reposting the
  same id returns the existing entry instead of double-recording the expense. Use it for anything
  batch or scripted.

### Scope: property vs unit

`unit_id` is authoritative. If you send both and they disagree, the call is rejected. When the user
names a property with one unit, send `property_id` alone and let the server resolve it.

## Working rules

**Confirm writes before making them.** Reads are free; a write lands in someone's tax record. State
the amount, date, category and property back to the user and get a yes before posting. Batch
imports: summarise what you are about to create, then post.

**Never fabricate a figure.** If a summary needs data you could not fetch, say what is missing.
Do not estimate, interpolate, or fill a gap with a plausible number — this is bookkeeping, and a
made-up row is worse than a missing one.

**Amounts are money.** Keep two decimal places, don't round to "about $200", and quote totals
exactly as returned.

**Rate limits.** Responses carry `RateLimit-*` headers and a `429` means slow down, not fail. Back
off and retry rather than hammering. If you are creating many entries, pace them.

**Errors.** A `404` on an endpoint you found in the OpenAPI document usually means it is not enabled
for this account, not that the record is missing. A `401` means the key is wrong, revoked, or
missing the `Bearer ` prefix.

## Worked examples

Fetch the OpenAPI document for exact paths; these show the shape and the judgement calls.

**"Log the $240 plumber invoice for 412 Oak, paid last Tuesday."**
1. `GET` the properties list; match "412 Oak". If two properties match, ask which.
2. Confirm: `$240.00`, `EXPENSE`, category `REPAIRS`, dated `2026-08-04`, 412 Oak.
3. `POST` to the ledger create endpoint with those fields in snake_case.

**"What did I spend on repairs across all properties last quarter?"**
1. `GET` the ledger list, filtered by date range and category.
2. If the response says there are more results, page through — do not total a truncated page and
   present it as the answer.
3. Report the exact total and the number of entries behind it.

**"How did Q2 look?"**
If a reporting summary endpoint appears in the OpenAPI document, use it — it returns income,
expenses and net already broken out by month, category and property, computed server-side, and it
will not disagree with the web app. It is **off by default**, so on most accounts it will not be
there. Fall back to paging the full ledger for the range and totalling it yourself — and page to
the end before reporting a total.

## Privacy

This is the user's financial data. Use it to answer what they asked and nothing else — don't
volunteer it into unrelated context, don't copy it into files or external services, and don't
retain figures beyond the task at hand.
