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.
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.
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.
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');
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.
| Scope | Can do |
|---|---|
| read | All GET endpoints |
| read & write | Everything read can, plus POST / PATCH |
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.
| Code | Meaning |
|---|---|
| 200 | OK |
| 201 | Created |
| 401 | Missing or invalid API key |
| 403 | Key lacks the write ability |
| 404 | Resource not found or not yours |
| 422 | Validation failed |
| 429 | Rate 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
Lists every property on your account.
Query parameters
| per_page int | Items per page, 1–100 (default 25) |
| page int | Page 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 int | Property ID |
| name string | Display name |
| city / state / postal_code | Location |
| status string | active · inactive |
| units_count int | Number of units |
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
Lists units, optionally filtered to one property.
Query parameters
| property_id int | Only units of this property |
| per_page int | 1–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
Active and past leases across your units.
Query parameters
| unit_id int | Leases on this unit |
| status string | active · 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
Rent and other charges/receipts.
Query parameters
| unit_id int | Payments for this unit |
| status string | succeeded · pending · failed |
| category string | e.g. Payment, Deposit |
{ "data": [ { "id": 90211, "unit_id": 198, "category": "Payment",
"amount": 2400, "status": "succeeded", "due_date": "2026-08-01" } ] }
Work orders
Maintenance work orders.
Query parameters
| priority string | low · medium · high |
{ "data": [ { "id": 771, "title": "Leaking faucet",
"priority": "high", "status": "in_progress", "cost_estimate": 180 } ] }
work_order.* webhooks in realtime.Leads
The leasing pipeline — read, create, and update leads as they move toward a signed lease.
List leads, newest first.
Query parameters
| stage string | newcontactedtouringappliedleased |
| source string | e.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": {…} }
Create a lead.
Body
| name string | required |
| email string | Optional |
| phone string | Optional |
| message string | Their 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" } }
Update a lead — advance its stage, set a follow-up, or attach notes. All fields optional; send only what changes.
Body
| stage string | new · contacted · touring · applied · leased · lost |
| next_follow_up_at date | ISO date of the next touch |
| notes string | Free text |
| target_rent number | Budget |
| move_in_date date | Desired move-in |
| lost_reason string | When 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
Add an endpoint
Developer / API → Webhooks → add your HTTPS URL, tick payment.succeeded. Copy the signing secret (shown once).
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.
2xx fast and process asynchronously.Topics & payloads
Subscribe any endpoint to one or more topics. The data object mirrors that resource's API shape.
| Topic | Fires when · data contains |
|---|---|
| payment.succeeded | A rent payment clears · the payment object |
| application.accepted | An application is accepted · the application/booking |
| lease.signed | A renter signs · the lease |
| lease.activated | A lease is countersigned & activated · the lease |
| maintenance_request.created | A resident submits a request · the request |
| work_order.created | A work order opens · the work order |
| work_order.status_changed | A work order changes status · the work order + new status |
| lead.created | A 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" } }