API documentation
Nestsen is a maintenance and compliance platform for UK letting and managing agents. This page covers the surface an integration partner needs: showing Nestsen data inside another system, and receiving events from Nestsen as they happen. The full REST reference, with request and response schemas for every endpoint, is published at app.nestsen.com/api/docs (Swagger UI). For partner onboarding, contact info@nestsen.com.
Two mechanisms, two directions
Which one applies depends on who is calling. No customer credentials are ever exchanged between the two systems.
| Mechanism | Direction | Headers | Scope |
|---|---|---|---|
| REST API | The hub calls Nestsen | X-API-Key, or Authorization: Bearer <key> | One company, scoped read / write / admin |
For the REST API, customers create per-company API keys in Admin → API Management and share the key with the partner directly. Keys are scoped read, write or admin, and to exactly one company.
Events from Nestsen (outbound webhooks)
A customer, or a partner acting on their behalf with a write key, registers an endpoint to receive events as they happen:
| Method | Path | Purpose |
|---|---|---|
| POST | /api/outbound-webhooks | Register an endpoint. Body { url, events[], secret }. The secret is returned once, in the create response, and never again. |
| GET / PUT / DELETE | /api/outbound-webhooks/:id | List, update or remove an endpoint. |
| POST | /api/outbound-webhooks/:id/test | Send a synthetic test event to the endpoint. |
| GET | /api/outbound-webhooks/:id/deliveries | Delivery history, including status and response code per attempt. |
Every delivery is a POST to your URL with a JSON body and three headers:
X-Nestsen-Event: ticket_created
X-Nestsen-Signature: sha256=<hex hmac>
X-Nestsen-Delivery: 4821
{
"event": "ticket_created",
"timestamp": "2026-09-17T10:00:00.000Z",
"nestsen_delivery_id": 4821,
"data": { "maintenanceRequestId": 456, "propertyAddress": "12 High Street", "summary": "Kitchen tap dripping constantly" }
}X-Nestsen-Signature is an HMAC-SHA256 of the exact request body, using your webhook secret as the key, hex-encoded and prefixed with sha256=. Verify it before trusting the payload:
const crypto = require("crypto");
function isValidNestsenWebhook(rawBody, signatureHeader, secret) {
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
}Compute the signature over the raw request body, not a re-serialised copy. A delivery that fails or times out is retried up to five times, at increasing intervals (30 seconds, 2 minutes, 10 minutes, 1 hour, then 6 hours), and every attempt is recorded against the delivery so it shows up in the deliveries endpoint above.
Maintenance
| ticket_created | A new maintenance request was raised. |
| ticket_status_changed | A request moved to a new status. |
| ticket_cancelled | A request was cancelled. |
| tradesperson_declined | A tradesperson declined a job offer. |
| offer_expired | A job offer expired unanswered. |
| tenant_availability_submitted | A tenant submitted their availability for a visit. |
Compliance
| compliance_case_opened | A compliance case was opened. |
| compliance_case_stage_completed | A compliance case moved to its next stage. |
| compliance_case_breached | A compliance case passed its statutory deadline. |
| compliance_case_closed | A compliance case was closed. |
Complaints
| complaint.created | A complaint was logged. |
| complaint.categorised | A complaint was assigned a category. |
| complaint.updated | A complaint's handoff status changed. |
Access grants
| access_grant_requested | A tenant was asked to confirm access arrangements. |
| access_grant_submitted | A tenant submitted access arrangements. |
| access_grant_expiring | An access grant is due to expire shortly. |
| access_grant_expired | An access grant expired unused. |
| access_grant_superseded | An access grant was replaced by a newer one. |
| access_grant_revoked | An access grant was revoked. |
| access_grant_chase_advanced | A chase for missing access arrangements moved to its next step. |
REST endpoints partners use most
A wider set of endpoints exists under /api/external with full request and response schemas in the Swagger UI. These are the ones most partner integrations reach for first — click a row for its parameters and an example response.
| Method | Path | Key scope | |
|---|---|---|---|
List properties for the company. | |||
Look up a property by external reference. | |||
Create or update a property by external reference. | |||
Create or update a landlord by external reference. | |||
Create or update a tenant by external reference. | |||
Create or update a tenancy by external reference. | |||
List maintenance requests for a property. | |||
Get a single maintenance request. | |||
Raise a maintenance request. | |||
Update a maintenance request. | |||
Attach photos to a maintenance request. | |||
Get the status history for a maintenance request. | |||
List maintenance category codes. | |||
Rate limits and environments
Preprod, for partner testing, is at https://app.preprod.nestsen.com. Production is at https://app.nestsen.com. A test company with sample data is provisioned on request, so integration work does not need to start against live customer data.
The default for the external API is 300 requests per 15 minutes per IP address, and 100 requests per 15 minutes per API key. The two limits apply to every /api/external route, not just one endpoint. Higher limits are available by arrangement.