📘 Developer reference

MyRentalSpot API

A REST API for your portfolio — read properties, units, leases, payments, work orders and leasing leads; create & update leads; and receive signed webhooks the moment things happen. JSON in, JSON out, over HTTPS.

Base URLhttps://www.myrentalspot.com/api/v1

The API is versioned in the path (/v1). Every response is JSON wrapped in a data envelope; lists add a meta block for pagination.

Quickstart

From zero to your first call in three steps.

1

Create an API key

In MyRentalSpot go to Account → Developer / API → Create key. Choose Read for read-only access, or Read & write if you'll create or update data. Copy the key — it's shown once.

2

Make your first request

# List your properties
curl https://www.myrentalspot.com/api/v1/properties \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://www.myrentalspot.com/api/v1/properties", {
  headers: { Authorization: "Bearer YOUR_API_KEY" }
});
const { data } = await res.json();
$res = Http::withToken('YOUR_API_KEY')
  ->get('https://www.myrentalspot.com/api/v1/properties');
$data = $res->json('data');
3

Read the response

// 200 OK
{
  "data": [
    { "id": 128, "name": "56 Longridge Rd", "city": "Brighton", "state": "MA", "units_count": 3 }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 4 }
}

Authentication

Every request needs a bearer key in the Authorization header. Keys are managed in Account → Developer / API and come in two scopes.

ScopeCan do
readAll GET endpoints
read & writeEverything read can, plus POST / PATCH
🔒 A write call made with a read-only key returns 403 Forbidden. Treat keys like passwords — rotate or revoke any that leak from the Developer page.

Rate limits

60 requests per minute per key. Over the limit returns 429. Each response carries rate headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
Retry-After: 41   # seconds, only on 429

Errors

Standard HTTP codes; the body always has a message, and validation errors add a per-field errors object.

CodeMeaning
200OK
201Created
401Missing or invalid API key
403Key lacks the write ability
404Resource not found or not yours
422Validation failed
429Rate limit exceeded

422 example

// 422 Unprocessable
{ "message": "The name field is required.",
  "errors": { "name": ["The name field is required."] } }

Pagination

List endpoints return up to per_page items (default 25, max 100). Pass ?page= and ?per_page=. The meta block tells you where you are.

curl "…/api/v1/payments?per_page=50&page=2" -H "Authorization: Bearer KEY"

"meta": { "current_page": 2, "per_page": 50, "total": 318 }

Properties

GET/propertiesread

Lists every property on your account.

Query parameters

per_page intItems per page, 1–100 (default 25)
page intPage number
curl https://www.myrentalspot.com/api/v1/properties \
  -H "Authorization: Bearer YOUR_API_KEY"
const r = await fetch("…/api/v1/properties",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Http::withToken('YOUR_API_KEY')->get('…/api/v1/properties');

Response

{ "data": [
    { "id": 128, "name": "56 Longridge Rd", "address1": "56 Longridge Rd",
      "city": "Brighton", "state": "MA", "postal_code": "02135",
      "status": "active", "units_count": 3 } ],
  "meta": { "current_page": 1, "per_page": 25, "total": 4 } }

Response fields

id intProperty ID
name stringDisplay name
city / state / postal_codeLocation
status stringactive · inactive
units_count intNumber of units
GET/properties/{id}read

Retrieve one property by ID.

curl …/api/v1/properties/128 -H "Authorization: Bearer KEY"
// 200 { "data": { "id": 128, "name": "56 Longridge Rd", "units_count": 3 } }

Units

GET/unitsread

Lists units, optionally filtered to one property.

Query parameters

property_id intOnly units of this property
per_page int1–100 (default 25)
curl "…/api/v1/units?property_id=128" -H "Authorization: Bearer KEY"
{ "data": [ { "id": 198, "property_id": 128, "name": "Unit 2",
    "beds": 2, "baths": 1, "rent": 2400, "is_occupied": true } ] }

Leases

GET/leasesread

Active and past leases across your units.

Query parameters

unit_id intLeases on this unit
status stringactive · pending · terminated
{ "data": [ { "id": 5567, "unit_id": 198, "status": "active",
    "check_in": "2026-01-01", "monthly_rent": 2400,
    "primary_resident": { "name": "Jane Tenant", "email": "[email protected]" } } ] }

Payments

GET/paymentsread

Rent and other charges/receipts.

Query parameters

unit_id intPayments for this unit
status stringsucceeded · pending · failed
category stringe.g. Payment, Deposit
{ "data": [ { "id": 90211, "unit_id": 198, "category": "Payment",
    "amount": 2400, "status": "succeeded", "due_date": "2026-08-01" } ] }

Work orders

GET/work-ordersread

Maintenance work orders.

Query parameters

priority stringlow · medium · high
{ "data": [ { "id": 771, "title": "Leaking faucet",
    "priority": "high", "status": "in_progress", "cost_estimate": 180 } ] }
✍️ Creating/updating work orders via the API is on the roadmap — a work order links to a maintenance task. For now they're read-only; you still get work_order.* webhooks in realtime.

Leads

The leasing pipeline — read, create, and update leads as they move toward a signed lease.

GET/leadsread

List leads, newest first.

Query parameters

stage stringnewcontactedtouringappliedleased
source stringe.g. ai_chat, tour_request
{ "data": [ { "id": 1201, "name": "Jane Doe", "email": "[email protected]",
    "phone": "(555) 010-2020", "stage": "new", "source": "ai_chat",
    "created_at": "2026-08-22T14:03:00Z" } ], "meta": {…} }
POST/leadswrite

Create a lead.

Body

name stringrequired
email stringOptional
phone stringOptional
message stringTheir enquiry
curl -X POST …/api/v1/leads \
  -H "Authorization: Bearer YOUR_WRITE_KEY" \
  -d name="Jane Doe" -d email="[email protected]" \
  -d message="Interested in the 2BR"
await fetch("…/api/v1/leads", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_WRITE_KEY",
             "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Jane Doe", email: "[email protected]" })
});
Http::withToken('YOUR_WRITE_KEY')->post('…/api/v1/leads', [
  'name' => 'Jane Doe', 'email' => '[email protected]',
]);
// 201 Created
{ "data": { "id": 1201, "name": "Jane Doe", "stage": "new", "source": "api" } }
PATCH/leads/{id}write

Update a lead — advance its stage, set a follow-up, or attach notes. All fields optional; send only what changes.

Body

stage stringnew · contacted · touring · applied · leased · lost
next_follow_up_at dateISO date of the next touch
notes stringFree text
target_rent numberBudget
move_in_date dateDesired move-in
lost_reason stringWhen marking lost
curl -X PATCH …/api/v1/leads/1201 \
  -H "Authorization: Bearer YOUR_WRITE_KEY" \
  -d stage="contacted" -d next_follow_up_at="2026-09-01" \
  -d notes="Called — tour booked Sat"
// 200 OK
{ "data": { "id": 1201, "stage": "contacted" } }

Guide: Sync new leads to your CRM

Two ways, depending on how fresh you need it.

Realtime (recommended)

Subscribe a webhook to lead.created. Every new lead — including ones the AI leasing agent captures — POSTs to your endpoint instantly. See Webhooks.

Polling

# Every 5 min, pull new leads and push into your CRM
curl "…/api/v1/leads?stage=new&per_page=100" \
  -H "Authorization: Bearer YOUR_API_KEY"
# → upsert each data[] row by id into your system

Write back

When your CRM advances the lead, mirror it back with PATCH /leads/{id} so the MyRentalSpot pipeline stays in sync.

Guide: Get notified when rent is paid

1

Add an endpoint

Developer / API → Webhooks → add your HTTPS URL, tick payment.succeeded. Copy the signing secret (shown once).

2

Verify & handle

// Node/Express receiver
app.post("/webhooks/mrs", (req, res) => {
  const sig = "sha256=" + hmacSha256(req.rawBody, SECRET);
  if (sig !== req.headers["x-mrs-signature"]) return res.sendStatus(400);
  const { event, data } = req.body;
  if (event === "payment.succeeded") notifyOps(data);
  res.sendStatus(200); // ack fast
});

Webhooks

Register an HTTPS endpoint under Developer / API and get a signed POST the moment an event fires.

Delivery format

POST https://your-server.com/webhooks/mrs
X-MRS-Event: payment.succeeded
X-MRS-Signature: sha256=9f86d0818…
X-MRS-Delivery: 8f3a2b10-…

{ "event": "payment.succeeded",
  "created_at": "2026-08-22T14:10:00Z",
  "data": { "id": 90211, "unit_id": 198, "amount": 2400, "status": "succeeded" } }

Verify the signature

Compute HMAC-SHA256 of the raw body with your endpoint secret; constant-time compare to X-MRS-Signature.

🔁 Non-2xx replies retry up to 5× with backoff (1m → 3h). Acknowledge with 2xx fast and process asynchronously.

Topics & payloads

Subscribe any endpoint to one or more topics. The data object mirrors that resource's API shape.

TopicFires when · data contains
payment.succeededA rent payment clears · the payment object
application.acceptedAn application is accepted · the application/booking
lease.signedA renter signs · the lease
lease.activatedA lease is countersigned & activated · the lease
maintenance_request.createdA resident submits a request · the request
work_order.createdA work order opens · the work order
work_order.status_changedA work order changes status · the work order + new status
lead.createdA new lead comes in · the lead

Example: lead.created

{ "event": "lead.created", "created_at": "2026-08-22T14:03:00Z",
  "data": { "id": 1201, "name": "Jane Doe", "stage": "new", "source": "ai_chat" } }