Help centre

Integrations & API

API keys and webhooks (for developers)

Use the havelo API to read and create properties, tenants and maintenance, and receive webhooks for real-time events.

This guide is for developers who want to connect their own systems to havelo. If you just want to link havelo to another app without code, use Zapier instead.

Integrations are available on the Pro plan and above.

API keys

Every request is authenticated with a personal API key.

  1. In havelo, open Settings and choose the Integrations tab.
  2. Click Create API key and give it a name.
  3. Copy the key immediately. It starts with hv_live_ and is shown only once.

Keep keys secret and out of version control. You can revoke a key at any time and it stops working instantly. Create a separate key per system, so you can revoke one without affecting the others.

Base URL

All endpoints live under https://api.havelo.co.uk/api/public/v1.

Authentication

Send your key on every request, either as a bearer token or an X-API-Key header:

Authorization: Bearer hv_live_your_key_here

For example, to confirm your key works:

curl https://api.havelo.co.uk/api/public/v1/me -H "Authorization: Bearer hv_live_your_key_here"

Endpoints

MethodEndpointWhat it does
GET/meThe account the key belongs to
GET/propertiesList your properties
POST/propertiesCreate a property
GET/properties/{id}Get one property
GET/tenantsList your tenants
POST/tenantsCreate a tenant
GET/maintenanceList maintenance requests
POST/maintenanceCreate a maintenance request

List endpoints return newest first, in the shape { "object": "list", "data": [ ... ] }. Every request is scoped to the account that owns the key, so you only ever see your own data.

Creating records

Send a JSON body with Content-Type: application/json. A successful create returns 201 and the created object (see Response objects below).

POST /properties fields

FieldTypeRequiredNotes
address_line_1stringYesFirst line of the address
citystringYesTown or city
postcodestringYesUK postcode
address_line_2stringNoSecond address line
property_typestringNoDefaults to house. One of house, flat, terrace, semi-detached, detached, bungalow, hmo, other
bedroomsintegerNoNumber of bedrooms
bathroomsintegerNoNumber of bathrooms
monthly_rentnumberNoMonthly rent in GBP

POST /tenants fields

FieldTypeRequiredNotes
property_idintegerYesA property you own
first_namestringYes
last_namestringYes
emailstringNo
phonestringNo

POST /maintenance fields

FieldTypeRequiredNotes
property_idintegerYesA property you own
titlestringYesShort summary of the issue
descriptionstringNoFull detail
categorystringNoDefaults to other. One of plumbing, electrical, heating, appliance, structural, pest, garden, other
prioritystringNoDefaults to medium. One of low, medium, high, urgent

Example (create a repair):

curl -X POST https://api.havelo.co.uk/api/public/v1/maintenance -H "Authorization: Bearer hv_live_your_key_here" -H "Content-Type: application/json" -d '{"property_id": 1, "title": "Leaking tap", "priority": "high"}'

Response objects

Properties, tenants and maintenance requests are returned in these shapes (the same shapes are used in webhook payloads). Fields that can be empty are marked nullable.

Property

FieldTypeNotes
idintegerUnique id
objectstringAlways property
address_line_1string
address_line_2string, nullable
citystring
postcodestring
countrystring
property_typestring
bedroomsinteger, nullable
bathroomsinteger, nullable
statusstringFor example occupied or vacant
monthly_rentnumber, nullableGBP
created_atdatetimeISO 8601
updated_atdatetime, nullableISO 8601

Tenant

FieldTypeNotes
idintegerUnique id
objectstringAlways tenant
property_idintegerThe property they belong to
first_namestring
last_namestring
emailstring, nullable
phonestring, nullable
statusstringFor example active
created_atdatetimeISO 8601
updated_atdatetime, nullableISO 8601

Maintenance request

FieldTypeNotes
idintegerUnique id
objectstringAlways maintenance_request
property_idinteger
tenant_idinteger, nullableSet if a tenant reported it
titlestring
descriptionstring, nullable
categorystring
prioritystringlow, medium, high or urgent
severitystring, nullable
statusstringFor example reported, in_progress, completed
total_costnumber, nullableGBP
reported_by_tenantboolean
created_atdatetimeISO 8601
updated_atdatetime, nullableISO 8601
completed_atdatetime, nullableISO 8601

Status codes and errors

CodeMeaning
200Success (GET requests)
201Created (successful POST)
401Missing or invalid API key
404Resource not found, or not owned by your account
422Invalid request body (a required field is missing or the wrong type)

Errors return a JSON body of the form { "detail": "a human readable message" }.

Webhooks

Instead of polling, you can have havelo push events to your server the moment they happen.

  1. In Settings, then Integrations, add a webhook endpoint (a public https URL on your server).
  2. havelo sends a POST with a JSON body whenever a matching event fires.
  3. You can send a test delivery from the same screen.

Events

  • property.created
  • tenant.created
  • maintenance.created
  • maintenance.updated
  • maintenance.completed

Verifying a delivery

Each delivery includes these headers:

  • X-Havelo-Event: the event type, for example maintenance.created.
  • X-Havelo-Delivery: a unique id for the delivery.
  • X-Havelo-Signature: a signature in the form sha256=<hex>.

The signature is an HMAC-SHA256 of the exact request body, using your endpoint's signing secret (it starts with whsec_ and is shown when you create the webhook). Recompute it on your side and compare, to be sure the request really came from havelo. Reject anything that does not match.

Notes

  • All traffic is over HTTPS.
  • Keep your API keys and webhook secrets private. Rotate them if they are ever exposed.
  • Need a hand? Contact support.

Still stuck?

Send us a note (we reply within one working day).