Using the API
Pagination and filtering
List endpoints page the same way everywhere: page and limit in, a data array and a total out.
Parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
page | integer | 1 | One based. Asking for a page past the end returns an empty data array, not an error. |
limit | integer | 20 or 10 | Maximum 100. Projects default to 20, most nested lists to 10. |
Response shape
{
"success": true,
"message": "Projects retrieved",
"status_code": 200,
"response_object": {
"data": [],
"total": 143,
"page": 2,
"limit": 20,
"total_pages": 8,
"tab_counts": { "all": 143, "active": 96, "closed": 31, "completed": 16 }
}
}
tab_counts appears on project lists and mirrors the counters in the portal. It is calculated across the whole result set, not the current page, so you can render counts without a second call.
Walking every page
async function allProjects(key) {
const results = [];
let page = 1;
let totalPages = 1;
while (page <= totalPages) {
const res = await fetch(
`https://api.iwiconnect.com/projects?page=${page}&limit=100`,
{ headers: { Authorization: `Bearer ${key}` } }
);
const { response_object } = await res.json();
results.push(...response_object.data);
totalPages = response_object.total_pages;
page += 1;
}
return results;
}
Pagination is offset based, so a record created while you are paging can shift rows between pages. For a nightly sync that rarely matters. If you are paging a busy account mid-afternoon, sort out duplicates by id on your side.
Filtering projects
GET /projects takes filters as query parameters. Repeat a parameter to pass several values, and note that the values are the enum names, not the labels the portal shows.
| Parameter | Example | Notes |
|---|---|---|
search | search=Waikanae | Matches project name, reference and address. |
type | type=LAND_USE_CONSENT | See enumerations. |
status | status=AWAITING_RESPONSE | Lifecycle status. |
priority | priority=HIGH | Derived from project type. |
organisation | organisation=Fulton+Hogan | Spelled the New Zealand way in the query string. |
local_authority | local_authority=Kāpiti+Coast+District+Council | URL encode the macron. |
assigned_to | assigned_to=0b6a51d2-... | User id. |
active_status | active_status=active | One of all, active, closed, completed. |
curl -G https://api.iwiconnect.com/projects \ -H "Authorization: Bearer $IWICONNECT_KEY" \ --data-urlencode 'active_status=active' \ --data-urlencode 'type=LAND_USE_CONSENT' \ --data-urlencode 'type=SUBDIVISION_CONSENT' \ --data-urlencode 'limit=50'
Filters combine with AND across parameters and OR within a repeated parameter. The request above returns active projects that are either land use or subdivision consents.
Keeping a copy in sync
There are no webhooks yet, so a scheduled pull is the pattern. Page GET /projects with active_status=active every ten to fifteen minutes and compare updated_on against what you hold. For anything that moved, fetch the project and its engagements. Closed and completed projects change rarely, so a nightly full sweep is enough for those.