curl --request GET \
--url https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access \
--header 'Authorization: Bearer <token>' \
--header 'X-BuildPass-Api-Version: <x-buildpass-api-version>'import requests
url = "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access"
headers = {
"X-BuildPass-Api-Version": "<x-buildpass-api-version>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-BuildPass-Api-Version': '<x-buildpass-api-version>',
Authorization: 'Bearer <token>'
}
};
fetch('https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-BuildPass-Api-Version: <x-buildpass-api-version>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-BuildPass-Api-Version", "<x-buildpass-api-version>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access")
.header("X-BuildPass-Api-Version", "<x-buildpass-api-version>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-BuildPass-Api-Version"] = '<x-buildpass-api-version>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "grant_clgbsb90b001qjy0f0eo1hspp",
"worker": {
"id": "wkr_clgbsb90b001qjy0f0eo1hspp",
"fullName": "Alex Smith"
},
"status": "ACTIVE",
"grantedAt": "2026-09-14T23:00:00.000Z",
"revokedAt": null,
"createdAt": "2026-09-14T23:00:00.000Z",
"updatedAt": "2026-09-14T23:00:00.000Z"
}
],
"meta": {
"totalCount": 100,
"totalPages": 4,
"offset": 0,
"limit": 25
}
}{
"errors": [
{
"fieldName": "name",
"message": "This field is required."
}
]
}List site access (planned)
Proposed worker-project access feed for access-control providers.
curl --request GET \
--url https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access \
--header 'Authorization: Bearer <token>' \
--header 'X-BuildPass-Api-Version: <x-buildpass-api-version>'import requests
url = "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access"
headers = {
"X-BuildPass-Api-Version": "<x-buildpass-api-version>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-BuildPass-Api-Version': '<x-buildpass-api-version>',
Authorization: 'Bearer <token>'
}
};
fetch('https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-BuildPass-Api-Version: <x-buildpass-api-version>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-BuildPass-Api-Version", "<x-buildpass-api-version>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access")
.header("X-BuildPass-Api-Version", "<x-buildpass-api-version>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.buildpass.global/builders/{builderId}/projects/{projectId}/site-access")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-BuildPass-Api-Version"] = '<x-buildpass-api-version>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "grant_clgbsb90b001qjy0f0eo1hspp",
"worker": {
"id": "wkr_clgbsb90b001qjy0f0eo1hspp",
"fullName": "Alex Smith"
},
"status": "ACTIVE",
"grantedAt": "2026-09-14T23:00:00.000Z",
"revokedAt": null,
"createdAt": "2026-09-14T23:00:00.000Z",
"updatedAt": "2026-09-14T23:00:00.000Z"
}
],
"meta": {
"totalCount": 100,
"totalPages": 4,
"offset": 0,
"limit": 25
}
}{
"errors": [
{
"fieldName": "name",
"message": "This field is required."
}
]
}read:site_access scope are planned and not yet available
in production or sandbox. This page is published for integration design and
partner review. It does not announce API availability or a delivery date.Access is an explicit decision
Each grant represents one worker’s access to one project.ACTIVE permits site
access; REVOKED removes it. Revoking access on one project does not revoke access
on another. Induction review may support an explicit grant, but an induction is
not itself an access grant.
The grant ID uses grant_, the worker ID uses wkr_, and the path requires
buil_ and proj_ IDs. A worker keeps the same ID across employer changes.
Removing a subcontractor does not automatically revoke worker access. Providers
must use explicit grant status, not employer status or absence from a list.
Lifecycle and example
A grant keeps its ID across revocation and regrant.grantedAt records the most
recent grant; revokedAt is null while active. Revoking a grant retains the row
and advances updatedAt so the change remains discoverable.
{
"data": [
{
"id": "grant_clgbsb90b001qjy0f0eo1hspp",
"worker": {
"id": "wkr_clgbsb90b001qjy0f0eo1hspp",
"fullName": "Alex Smith"
},
"status": "REVOKED",
"grantedAt": "2026-09-14T23:00:00.000Z",
"revokedAt": "2026-09-15T00:10:00.000Z",
"createdAt": "2026-09-14T23:00:00.000Z",
"updatedAt": "2026-09-15T00:10:00.000Z"
}
],
"meta": {
"totalCount": 1,
"totalPages": 1,
"offset": 0,
"limit": 25
}
}
Proposed polling contract
- Initial synchronization omits
updatedAfterandstatusand reads all pages. - Incremental synchronization supplies
updatedAfteras an exclusive UTC timestamp (updatedAt > updatedAfter) and omitsstatusto include revocations. - Results are ordered by
updatedAtascending, then grant ID ascending. Apply updates by grant ID. The final checkpoint protocol must handle equal timestamps and changes during pagination without skipping records. - The proposed page size is 25 by default, up to 100, using
offsetandlimitand the standardmetaresponse. This does not change existing endpoints’ limits. - Changes to embedded worker data, including
fullName, must also advance the grant’s feed timestamp.
Contract decisions still to confirm
The fields above are the proposed grant feed. Employer projection, worker photos and RFID credentials are separate contract work and are not included in this response yet. Photo or credential availability must not create or revoke a grant. Before implementation, confirm deletion and worker-merge reconciliation, builder offboarding, project archive policy, credential and biometric deletion, and the final polling consistency rules. Gate activity ingestion is a separate planned endpoint.Authorizations
The access token received from the authorization server in the OAuth 2.0 flow.
Headers
What API version to use.
v1 "v1"
Builder database region; defaults to au1.
au1, us1 Path Parameters
The ID of the builder
"buil_clgbsb90b001qjy0f0eo1hspp"
The ID of the project
"proj_clgbsb90b001qjy0f0eo1hspp"
Query Parameters
The number of items to skip before starting to collect the result set
x >= 00
Planned page size for this endpoint (default 25, maximum 100). Existing endpoints retain their documented limits.
1 <= x <= 10025
Proposed exclusive UTC lower bound: return grants whose updatedAt is strictly greater than this timestamp. Omit for initial/full sync. Poll without a status filter to receive revocations. Final pagination consistency and checkpoint rules will be confirmed before availability.
"2026-09-15T00:00:00.000Z"
Optional status filter for browsing. Omit during synchronization: filtering ACTIVE would hide revocations.
ACTIVE, REVOKED