Estate Ops

Estate Ops API

Read your estate's data from your own systems. Read-only, over plain web requests, in JSON, CSV or GeoJSON.

What it's for

The feed lets the systems you already use pull your estate's records straight from Estate Ops — an accounts package, a Power BI or Excel report, a map in QGIS — instead of someone exporting and re-typing them. It only ever reads. Nothing sent to the feed can change a record.

It comes with the API & data feed add-on, £350 a month per estate — see pricing.

Getting a key

An estate admin opens Admin → API access in the portal, switches the add-on on and chooses Create a key. Only estate admins can see that page.

  • Give each system its own key, named after it, so one can be revoked without the others.
  • The key is shown once, when it is created. Copy it then — it can't be shown again. Lose it, and you revoke it and make another.
  • A key can be given an end date, and revoked at any time. Either stops it straight away.
  • Switching the add-on off stops every key at once.

That page also shows your feed address — the start of every request below, written here as https://ourbcrppvxmdukfnemgc.supabase.co/functions/v1/data-feed/v1.

Signing requests

Send the key in an Authorization header on every request:

Authorization: Bearer YOUR_KEY

Treat a key like a password: keep it out of shared spreadsheets, emails and code that others can read. If one might have been seen, revoke it.

Listing datasets

curl -H "Authorization: Bearer YOUR_KEY" https://ourbcrppvxmdukfnemgc.supabase.co/functions/v1/data-feed/v1/datasets

Returns the datasets your key can read, by name. The list is live — it follows your key's scopes and grows as Estate Ops does — so it, not this page, is the reference for what is available.

Reading a dataset

GET https://ourbcrppvxmdukfnemgc.supabase.co/functions/v1/data-feed/v1/datasets/{name}?format=json&limit=1000&cursor=…&changed_since=…
OptionWhat it does
formatjson (the default), csv for spreadsheets, or geojson for maps.
limitHow many rows to return, up to 1,000.
cursorWhere to carry on from — the next_cursor from the page before.
changed_sinceOnly rows changed after this time. Use the watermark from your last run (below).

A JSON response looks like this:

{
  "data": [ { "id": "…", … }, … ],
  "next_cursor": "…",
  "has_more": true,
  "watermark": "2026-09-27T10:15:00Z"
}

Paging. While has_more is true, ask again with cursor set to next_cursor.

CSV, for spreadsheets. Add format=csv. The file is the rows only; the next cursor comes back in the X-Next-Cursor response header. In Excel or Power BI, use Data → From Web, paste the address and add the Authorization header.

GeoJSON, for maps. Add format=geojson to a dataset that has a map position — pins, for example — and load it into QGIS or any GIS as a layer from a web address, with the Authorization header set.

Keeping a copy up to date

The feed serves rows once they have been unchanged for about two minutes, so a record being edited right now arrives on your next run rather than half-finished. Every response carries a watermark: the time it is safe to carry on from next time.

  1. First run: read the dataset with no changed_since, page by page, and keep the watermark from the first page.
  2. Save each row in your system by its id — add it if new, replace it if you have it.
  3. Next run: read with changed_since set to the watermark you kept, and keep the new one.
  4. Then ask for deletions since the same watermark (below) and remove those rows from your copy.

A row can occasionally come back twice across runs; saving by id makes that harmless.

Deleted records

GET https://ourbcrppvxmdukfnemgc.supabase.co/functions/v1/data-feed/v1/deletions?since=2026-09-27T10:15:00Z

Lists records deleted since that time — whether moved to Recently deleted or removed for good — so your copy can drop them. Deletions are kept for 90 days. Ask for anything older and you get a 410: read the dataset again from the start instead.

Records the law or your accounts rely on — game and cartridge records, sales, inspections and the like — are never deleted: they are voided with a reason. A voided record is listed here like any other deletion, with a void_reason saying why.

What a key can read

Each key is given scopes when it is created.

ScopeWhat it covers
coreEveryday estate records — everything that isn't staff, certificate or firearms data. Every key has it.
staffStaff hours, leave and personal records.
certificatesThe certificates register. Every read is recorded in the estate's audit trail.
firearmsArmoury data. Needs a valid firearms certificate and the Armoury add-on. Every read is recorded in the estate's audit trail.

Where people are is never included.The location of any person — a lone worker's position, say — is never served, whatever scopes a key has.

Limits

  • Up to 1,000 rows a page.
  • 120 requests a minute for each key. Past that you get a 429 — wait a minute and carry on.
  • Rows appear about two minutes after their last change.
  • Deletions are kept for 90 days.

Errors

CodeWhat it meansWhat to do
401The key is wrong, revoked or past its end date.Check the header, or create a new key.
403The API & data feed add-on is switched off.An estate admin switches it on in API access.
404No such dataset, or not one this key's scopes cover.Check /datasets for the names your key can read.
410The since time for deletions is more than 90 days ago.Read the dataset again from the start.
429Too many requests from this key.Wait a minute, then carry on.