# Authentication token Source: https://developer.buildpass.global/api-reference/authentication/post POST /oauth/token Generate an OAuth token to access the BuildPass API # Bulk upload attachments Source: https://developer.buildpass.global/api-reference/builders/attachments/bulk-upload POST /builders/{builderId}/attachments/bulk-upload Upload multiple attachment files and receive attachment references for a later resource create or upsert request. Include type=attachment, or per-file type:N=attachment fields, so BuildPass can route each file to the correct storage family. For example, use the returned references to bulk upsert photos. Requires a valid authenticated request for the builder. No resource-specific scope is required for upload. Uploads multiple attachment files into BuildPass-managed attachment storage and returns attachment references. Include `type=attachment` in the multipart body to apply the same type to all files, or `type:0=attachment`, `type:1=attachment`, and so on to set a type per file. The `type` tells BuildPass which storage family to use; `attachment` is the only externally supported upload type for now. For example, you can use each returned `{ key, regionId, type }` to bulk upsert photos by passing it as `photos[].imageAttachment`. # Create an attachment upload URL Source: https://developer.buildpass.global/api-reference/builders/attachments/presign POST /builders/{builderId}/attachments/presign Create a short-lived, builder-scoped S3 PUT URL for an image up to 40 MiB. Upload the bytes directly with the declared Content-Type, then use the returned attachment reference when creating or bulk-upserting photos. Requires a valid authenticated request for the builder. No resource-specific scope is required. Creates a short-lived, builder-scoped S3 upload URL for an image up to 40 MiB. The endpoint returns `200 OK` because it creates an upload intent rather than a persisted BuildPass resource. Send the image bytes directly to the returned `uploadUrl` with `PUT` and the exact returned `uploadHeaders`. Then use the returned `{ key, regionId, type }` attachment reference when creating or bulk-upserting photos. The External API validates the image bytes, type, and final size when the attachment reference is consumed. ## Sending the upload Server-side clients should send every returned `uploadHeaders` value verbatim: ```ts theme={null} await fetch(uploadUrl, { method: "PUT", headers: uploadHeaders, body: imageBytes, }); ``` Do not append parameters such as `charset` to `Content-Type`, because changing a signed header makes S3 reject the request. Browser Fetch APIs do not allow JavaScript to set `Content-Length`; in a browser, send the returned `Content-Type`, use the original `File` as the body, and ensure `File.size` exactly matches the `size` used to create the upload URL. The browser will derive the matching content length. # Upload attachment Source: https://developer.buildpass.global/api-reference/builders/attachments/upload POST /builders/{builderId}/attachments/upload Upload one attachment file and receive an attachment reference for a later resource create request. Include type=attachment so BuildPass can route the file to the correct storage family. For example, use the returned reference to create a photo. Requires a valid authenticated request for the builder. No resource-specific scope is required for upload. Uploads one attachment file into BuildPass-managed attachment storage and returns an attachment reference. Include `type=attachment` in the multipart body. The `type` tells BuildPass which storage family to use; `attachment` is the only externally supported upload type for now. For example, you can use the returned `{ key, regionId, type }` to create a photo by passing it as `imageAttachment`. # Get builder Source: https://developer.buildpass.global/api-reference/builders/get GET /builders/{id} Get a builder that you are authorised to access # List builders Source: https://developer.buildpass.global/api-reference/builders/list GET /builders Get all builders that you are authorised to access # Create meeting Source: https://developer.buildpass.global/api-reference/builders/meetings/create POST /builders/{builderId}/meetings Create a draft meeting for a builder # End meeting Source: https://developer.buildpass.global/api-reference/builders/meetings/end POST /builders/{builderId}/meetings/{meetingId}/end End a meeting # List meetings Source: https://developer.buildpass.global/api-reference/builders/meetings/list GET /builders/{builderId}/meetings List meetings for a builder # List meeting notes Source: https://developer.buildpass.global/api-reference/builders/meetings/notes/list GET /builders/{builderId}/meetings/{meetingId}/notes List notes for a meeting # Create or update meeting note Source: https://developer.buildpass.global/api-reference/builders/meetings/notes/post POST /builders/{builderId}/meetings/{meetingId}/notes Create or update a meeting note by externalSourceId and sourceApp # Start meeting Source: https://developer.buildpass.global/api-reference/builders/meetings/start POST /builders/{builderId}/meetings/{meetingId}/start Start a meeting # Update meeting Source: https://developer.buildpass.global/api-reference/builders/meetings/update PATCH /builders/{builderId}/meetings/{meetingId} Update a meeting # Create photo folder Source: https://developer.buildpass.global/api-reference/builders/photo-folders/create POST /builders/{builderId}/photo-folders Requires `write:photos`. Creates a gallery photo folder for the builder. Include `projectId` only when the folder should be mapped to a BuildPass project. # Delete photo folder Source: https://developer.buildpass.global/api-reference/builders/photo-folders/delete DELETE /builders/{builderId}/photo-folders/{folderId} Requires `write:photos`. Deletes an empty gallery folder. Folders containing photos or child folders return `409`. # Get photo folder Source: https://developer.buildpass.global/api-reference/builders/photo-folders/get GET /builders/{builderId}/photo-folders/{folderId} Requires `read:photos`. Returns one gallery folder for the authenticated builder. # List photo folders Source: https://developer.buildpass.global/api-reference/builders/photo-folders/list GET /builders/{builderId}/photo-folders Requires `read:photos`. Returns gallery folders for the builder. Optional filter: `projectId=proj_`. # Update photo folder Source: https://developer.buildpass.global/api-reference/builders/photo-folders/update PATCH /builders/{builderId}/photo-folders/{folderId} Requires `write:photos`. Updates a photo folder name or parent folder. Parent folders must belong to the same builder and project. # Bulk upsert photos Source: https://developer.buildpass.global/api-reference/builders/photo-gallery/bulk-upsert POST /builders/{builderId}/photo-gallery/bulk-upsert Bulk upsert external photos into a BuildPass photo folder idempotently. Requires `write:photos`. Bulk upserts photos into a project gallery folder. `projectId` is required and must belong to the builder. Upload attachment bytes first with `POST /builders/{builderId}/attachments/bulk-upload`, then pass each returned `{ key, regionId, type }` as `photos[].imageAttachment`. This endpoint accepts JSON only. Approved HTTPS `imageUrl` imports are supported only for hosts reviewed and enabled by BuildPass. If you want to import photos from your own image URL hosts, please contact BuildPass. The endpoint is idempotent by `metadata.externalSourceId`, so repeated sends skip existing photos. When syncing the same external source again, pass the previously returned `folderId` so new photos are added to the same BuildPass folder. Omit `folderId` for a different external source, even when the folder name and date are the same. Use `DELETE /builders/{builderId}/photo-gallery/bulk-upsert` with the same `externalSourceId` and the currently selected `projectId` to archive photos created for that external source and remove its now-empty persisted folder when possible. The project identifies the caller's authorized BuildPass context; the deletion target is resolved from the external source's persisted metadata, which allows cleanup after the selected project changes. `folderId` remains accepted for request compatibility but is not used as deletion authority. For a retry after a prior copy was archived, an unclaimed folder ID may be recreated in the authorized destination project; an ID already owned by another project is rejected. # Create photo Source: https://developer.buildpass.global/api-reference/builders/photos/create POST /builders/{builderId}/photos Create a gallery photo from an uploaded imageAttachment reference, or an approved HTTPS image URL. Requires `write:photos`. Creates a gallery photo record from JSON with an uploaded `imageAttachment` reference or an approved `imageUrl`. Upload image bytes first with `POST /builders/{builderId}/attachments/upload`, then pass the returned `{ key, regionId, type }` as `imageAttachment`. Approved HTTPS `imageUrl` imports are supported only for hosts reviewed and enabled by BuildPass. If you want to import photos from your own image URL hosts, please contact BuildPass. # Delete photo Source: https://developer.buildpass.global/api-reference/builders/photos/delete DELETE /builders/{builderId}/photos/{photoId} Requires `write:photos`. Archives the gallery photo attachment and returns the archived record with a short-lived signed `imageUrl`. # Get photo Source: https://developer.buildpass.global/api-reference/builders/photos/get GET /builders/{builderId}/photos/{photoId} Get a photo by id. The source defaults to GALLERY; specify the owning source to read a photo from another supported BuildPass UI area. Requires `read:photos`. Returns one active gallery photo attachment for the authenticated builder, including a short-lived signed `imageUrl`. # List photos Source: https://developer.buildpass.global/api-reference/builders/photos/list GET /builders/{builderId}/photos List photos for a builder. The source defaults to GALLERY and can be repeated to include photos shown in other BuildPass UI areas. Returns signed image URLs. Results are paginated with a default and maximum limit of 25. Requires `read:photos`. Returns active gallery photo attachments for the builder, including a short-lived signed `imageUrl`. Optional filters: `projectId=proj_` and `folderId=`. # Update photo Source: https://developer.buildpass.global/api-reference/builders/photos/update PATCH /builders/{builderId}/photos/{photoId} Requires `write:photos`. Updates gallery photo metadata including file name, description, captured date, or folder assignment. The response includes a fresh signed `imageUrl`. # Get project Source: https://developer.buildpass.global/api-reference/builders/projects/get GET /builders/{id}/projects/{projectId} Get a project for a builder # Get induction Source: https://developer.buildpass.global/api-reference/builders/projects/inductions/get GET /builders/{builderId}/projects/{projectId}/inductions/{identifierOrId} Get an induction by identifier (numeric) or ID (ind_ prefix) # List inductions for project Source: https://developer.buildpass.global/api-reference/builders/projects/inductions/list GET /builders/{builderId}/projects/{projectId}/inductions Get all inductions for a project # List projects Source: https://developer.buildpass.global/api-reference/builders/projects/list GET /builders/{id}/projects Get all projects for a builder # List subcontractor contacts Source: https://developer.buildpass.global/api-reference/subcontractors/contacts/list GET /subcontractors/{id}/contacts Get all contacts for a subcontractor # Get subcontractor Source: https://developer.buildpass.global/api-reference/subcontractors/get GET /subcontractors/{id} Get an active subcontractor. Builder-company records require includeBuilderCompany=true. # List inductions for subcontractor Source: https://developer.buildpass.global/api-reference/subcontractors/inductions/list GET /subcontractors/{id}/inductions Get all inductions for workers associated with a subcontractor # Get insurance document Source: https://developer.buildpass.global/api-reference/subcontractors/insurances/get GET /subcontractors/{id}/insurances/{insuranceId} Get a document for a subcontractor # List insurance documents Source: https://developer.buildpass.global/api-reference/subcontractors/insurances/list GET /subcontractors/{id}/insurances Get all insurances for a subcontractor # List subcontractors Source: https://developer.buildpass.global/api-reference/subcontractors/list GET /subcontractors Get active subcontractors under a builder. By default, this returns third-party subcontractors only. # Get prequalification Source: https://developer.buildpass.global/api-reference/subcontractors/prequalifications/get GET /subcontractors/{id}/prequalifications/{prequalId} Get a prequalification for a subcontractor # List prequalifications Source: https://developer.buildpass.global/api-reference/subcontractors/prequalifications/list GET /subcontractors/{id}/prequalifications Get all prequalifications for a subcontractor # List subcontractor projects Source: https://developer.buildpass.global/api-reference/subcontractors/projects/list GET /subcontractors/{id}/projects Get all projects assigned to a subcontractor # Get SWMS document Source: https://developer.buildpass.global/api-reference/subcontractors/swms/get GET /subcontractors/{id}/swms/{swmsDocId} Get a SWMS document for a third-party or builder-company subcontractor. # List SWMS documents Source: https://developer.buildpass.global/api-reference/subcontractors/swms/list GET /subcontractors/{id}/swms Get all SWMS documents for a third-party or builder-company subcontractor. Retrieve the builder-company subcontractor id from GET /subcontractors?includeBuilderCompany=true. # Get cost codes Source: https://developer.buildpass.global/api-reference/timesheets/costCodes GET /timesheets/cost-codes Get a list of cost codes configured for a builder # Get timesheet Source: https://developer.buildpass.global/api-reference/timesheets/get GET /timesheets/{timesheetId} Get a timesheet by ID # List timesheets Source: https://developer.buildpass.global/api-reference/timesheets/list GET /timesheets Get all timesheets for a builder # Get time types Source: https://developer.buildpass.global/api-reference/timesheets/timeTypes GET /timesheets/time-types Get a list of time types configured for a builder # Changelog Source: https://developer.buildpass.global/changelog Latest changes and improvements to the BuildPass API ## Recent updates *** ### July 24, 2026 - Idempotent photo gallery sync removal **[DELETE /builders/\/photo-gallery/bulk-upsert](/api-reference/builders/photo-gallery/bulk-upsert)** now locates an external photo page by its stable source metadata, even after the caller changes projects. Repeating a removal after the synced folder is already absent now returns a successful `deleted` response with empty deleted IDs instead of failing. Re-syncing an existing external photo page to a new project now removes all active prior-project copies before creating the replacement, preventing duplicate photos across projects. Destination folder creation is deferred until cleanup succeeds and is committed with the first photo, so failed or interrupted attempts do not leave empty folders behind. *** ### July 23, 2026 - Direct attachment uploads The new **[POST /builders/\/attachments/presign](/api-reference/builders/attachments/presign)** endpoint creates a short-lived, builder-scoped S3 upload URL for images up to 40 MiB. Uploading directly to the returned URL avoids the Vercel Function request-body limit on the existing multipart attachment endpoints. The returned attachment reference can be used with photo create and bulk-upsert requests. *** ### July 23, 2026 - Photos list pagination The photos list endpoint is now paginated, consistent with every other list endpoint. * **[GET /builders/\/photos](/api-reference/builders/photos/list)** - Now paginated with `offset`/`limit` * **Behavior change:** responses now default to `limit=25`; previously the entire photo set was returned. Integrators reading full galleries should page with `offset` until `meta.totalCount` is reached * `limit` and `offset` are validated like every other list endpoint: `limit` above `25` or malformed values now return a `400` instead of being silently ignored * Responses now include the `meta` pagination object *** ### July 23, 2026 - Access to builder-company SWMS and UI photo sources External API consumers can now opt into records that are represented separately in the BuildPass UI. * **[GET /subcontractors](/api-reference/subcontractors/list)** * Pass `includeBuilderCompany=true` to include the builder's internal company subcontractor record * The default remains `false`, so existing integrations continue to receive third-party subcontractors only * Responses now include `isBuilder` so the internal company record can be identified * Archived subcontractors are excluded and results have deterministic ordering * **[GET /subcontractors/\](/api-reference/subcontractors/get)** * Pass `includeBuilderCompany=true` to retrieve the internal company record returned by the opt-in list * **[GET /subcontractors/\/swms](/api-reference/subcontractors/swms/list)** and **[GET /subcontractors/\/swms/\](/api-reference/subcontractors/swms/get)** * SWMS documents can now be read for the builder-company subcontractor returned by the opt-in company list * **[GET /builders/\/photos](/api-reference/builders/photos/list)** and **[GET /builders/\/photos/\](/api-reference/builders/photos/get)** * Pass repeatable `source` parameters to read photos shown in other UI areas, for example `source=GALLERY&source=DEFECT` * Supported sources are `GALLERY`, `SITE_DIARY`, `PRE_START`, `CHECKLIST`, `ITP`, `PLATFORM_ACTION`, and `DEFECT` * The default remains `GALLERY`; photo write and folder endpoints remain gallery-only * SWMS, prequalification, and insurance list responses now report the requested `offset` and `limit` with calculated pagination totals. *** ### June 11, 2026 - Photos API We've added endpoints for integrators to work with BuildPass photo galleries, folders, and uploaded attachment references. #### Attachments * **[POST /builders/\/attachments/upload](/api-reference/builders/attachments/upload)** - Upload one attachment for later resource creation * Requires an authenticated builder request, with no resource-specific scope required * Requires `type=attachment` so BuildPass can route the file to the correct storage family * Returns `{ key, regionId, type }` plus a short-lived signed `imageUrl` * **[POST /builders/\/attachments/bulk-upload](/api-reference/builders/attachments/bulk-upload)** - Upload multiple attachments for later resource creation or upsert * Requires an authenticated builder request, with no resource-specific scope required * Requires `type=attachment`, or per-file `type:0=attachment` fields, so BuildPass can route each file to the correct storage family * For example, returned attachment references can be used as `photos[].imageAttachment` #### Photos * **[GET /builders/\/photos](/api-reference/builders/photos/list)** - List gallery photos for a builder * Filter by project and folder * Returns photo metadata and a short-lived signed `imageUrl` * **[POST /builders/\/photos](/api-reference/builders/photos/create)** - Create a photo attachment * Accepts an uploaded `imageAttachment` reference from the attachment upload endpoint * Supports approved HTTPS `imageUrl` imports for enabled hosts * Stores the image in BuildPass attachment storage * **[GET /builders/\/photos/\](/api-reference/builders/photos/get)** - Get a photo by id * **[PATCH /builders/\/photos/\](/api-reference/builders/photos/update)** - Update photo metadata or move a photo between folders * **[DELETE /builders/\/photos/\](/api-reference/builders/photos/delete)** - Archive a photo #### Photo Folders * **[GET /builders/\/photo-folders](/api-reference/builders/photo-folders/list)** - List photo folders for a builder * **[POST /builders/\/photo-folders](/api-reference/builders/photo-folders/create)** - Create a photo folder for a project * **[GET /builders/\/photo-folders/\](/api-reference/builders/photo-folders/get)** - Get a photo folder by id * **[PATCH /builders/\/photo-folders/\](/api-reference/builders/photo-folders/update)** - Update a folder name or parent folder * **[DELETE /builders/\/photo-folders/\](/api-reference/builders/photo-folders/delete)** - Delete an empty photo folder #### Photo Gallery Sync * **[POST /builders/\/photo-gallery/bulk-upsert](/api-reference/builders/photo-gallery/bulk-upsert)** - Bulk upsert external photo pages into a BuildPass photo folder * Accepts a returned folder id for repeated sends and skips existing photos * Uses `externalSourceId` metadata for idempotency * Returns created, skipped, and failed photo details * Supports deleting photos created for an external source with `DELETE /builders//photo-gallery/bulk-upsert` Photo and folder endpoints use the `read:photos` and `write:photos` scopes. Attachment upload endpoints require authentication but do not require a resource-specific scope. *** ### June 8, 2026 - Meetings API We've added endpoints for integrators to work with BuildPass meetings. #### Meetings * **[GET /builders/\/meetings](/api-reference/builders/meetings/list)** - List meetings for a builder * Filter by project, status, start date, and end date * Supports pagination with offset/limit * Returns meeting title, type, project, schedule, status, agenda, notes, and update metadata * **[POST /builders/\/meetings](/api-reference/builders/meetings/create)** - Create a draft meeting for a builder * Supports ad hoc meetings from external capture products * Optionally links the meeting to a specific project * **[PATCH /builders/\/meetings/\](/api-reference/builders/meetings/update)** - Update a meeting title * Allows external capture products to keep generated meeting names in sync with BuildPass * **[POST /builders/\/meetings/\/start](/api-reference/builders/meetings/start)** - Mark a meeting as running * **[POST /builders/\/meetings/\/end](/api-reference/builders/meetings/end)** - Mark a meeting as completed #### Meeting Notes * **[GET /builders/\/meetings/\/notes](/api-reference/builders/meetings/notes/list)** - List notes synced to a meeting * **[POST /builders/\/meetings/\/notes](/api-reference/builders/meetings/notes/post)** - Create or update a meeting note from an external source * Notes are upserted by `externalSourceId` * Template-backed meetings store synced notes in the meeting template response * Meetings without a template response store synced notes in the meeting notes field These endpoints use the `read:meetings` and `write:meetings` scopes. *** ### April 7, 2026 - Signed profile and builder asset URLs OAuth identity responses now expose signed image URLs for BuildPass profile and company branding data: * `GET /me` now returns `profilePictureUrl` * `GET /me` memberships now return `builderLogoUrl` * `GET /builders` and `GET /builders/{id}` now return `logoUrl` These fields are intended for integrations that want to mirror BuildPass profile photos or builder logos inside their own applications. *** ### January 7, 2026 - Complete OAuth 2.0 Authorization Server We've implemented a full-featured OAuth 2.0 Authorization Server, enabling BuildPass to act as an identity provider for third-party integrations. This comprehensive implementation supports multiple grant types, client types, and security best practices. #### OAuth 2.0 Endpoints BuildPass now provides a complete suite of OAuth 2.0 endpoints: * **`POST /oauth/token`** - Token endpoint for all grant types * Client Credentials Grant (server-to-server) * Authorization Code Grant (user authorization) * Refresh Token Grant (token renewal) * **`GET /oauth/authorize`** - Authorization endpoint for user consent * Interactive consent screen for builders * State parameter for CSRF protection * Support for pre-selecting builders * Secure session management * **`POST /oauth/revoke`** - Token revocation endpoint (RFC 7009) * Revoke access tokens or refresh tokens * Immediate token invalidation * Compliant with OAuth 2.0 security standards #### Grant Types Supported **1. Client Credentials Grant (RFC 6749 Section 4.4)** * Server-to-server authentication without user involvement * Ideal for backend services and automated integrations * Scoped access to builder data based on pre-configured connections **2. Authorization Code Grant with PKCE (RFC 7636)** * User authorization flow with proof key for code exchange * Support for web apps, mobile apps, and SPAs * 10-minute authorization code lifetime * Single-use codes with automatic revocation on reuse * Refresh token rotation for enhanced security **3. Refresh Token Grant (RFC 6749 Section 6)** * Obtain new access tokens without re-authorization * 30-day refresh token lifetime * Automatic token rotation on use #### Client Types **Confidential Clients** * Backend services and servers that can securely store a `client_secret` * Required to authenticate with both `client_id` and `client_secret` * Support for all grant types * HTTP Basic Authentication or request body credentials **Public Clients** * Mobile apps, SPAs, and desktop applications * Authenticate with only `client_id` (no secret required or allowed) * Must use PKCE with Authorization Code flow * Enhanced security through cryptographic proof #### Security Features **PKCE (Proof Key for Code Exchange) - RFC 7636** * Mandatory for all Authorization Code flows * Supports SHA256 (`S256`) and plain (`PLAIN`) challenge methods * Prevents authorization code interception attacks * Generates cryptographically secure code verifiers **Authorization Code Reuse Protection** * Single-use authorization codes * Automatic revocation of all refresh tokens if code is reused * Protects against replay attacks **Refresh Token Rotation** * New refresh token issued on every use * Old refresh token automatically revoked * Prevents token theft and replay attacks **Token Security** * JWT access tokens with HMAC-SHA256 signing * 1-hour access token lifetime * 30-day refresh token lifetime * Unique token IDs (jti claim) for tracking * Cache-Control: no-store headers on token responses **State Parameter Validation** * Required state parameter for CSRF protection * Validated on callback to prevent cross-site attacks **Redirect URI Validation** * Strict matching of registered redirect URIs * Prevents token theft through malicious redirects #### Token Structure **Access Tokens (JWT)** ```json theme={null} { "sub": "integrator_id", "client_id": "client_id", "builder_id": "builder_id", // For Authorization Code flow "iss": "https://api.buildpass.global", "aud": "https://api.buildpass.global", "scope": "read:builders read:subcontractors", "jti": "unique_token_id", "iat": 1234567890, "exp": 1234571490 // 1 hour from iat } ``` **Token Response Format** ```json theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600, "scope": "read:builders read:subcontractors", "refresh_token": "550e8400-e29b-41d4-a716-446655440000" } ``` #### Available Scopes Granular permission system for controlling API access: * `read:builders` - Access builder information * `read:subcontractors` - Access subcontractor data * `read:projects` - Access project information * `read:insurances` - Access insurance certificates * `read:prequalifications` - Access prequalification documents * `read:contacts` - Access contact information * `read:swms` - Access SWMS documents * `read:timesheets` - Access timesheet data * `read:inductions` - Access induction records Scopes are validated against: 1. Client's allowed scopes (configured per integration) 2. Audience-specific scope requirements 3. Builder connections (for Authorization Code flow) #### User Consent Flow **Authorization Request** ``` GET /oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=https://yourapp.com/callback& scope=read:builders+read:subcontractors& state=RANDOM_STATE& code_challenge=BASE64_CHALLENGE& code_challenge_method=S256 ``` **User Experience** 1. User redirected to BuildPass consent screen 2. Displays requested permissions and integrator information 3. User reviews and approves/denies access 4. Redirect to application with authorization code or error 5. Application exchanges code for tokens **Builder Selection** * Automatic selection for users with single builder access * Builder selection screen for users with multiple builders * Optional `builder_id` parameter to pre-select builder #### RFC Compliance BuildPass OAuth 2.0 implementation is fully compliant with: * βœ… **RFC 6749** - OAuth 2.0 Authorization Framework * Client Credentials Grant (Section 4.4) * Authorization Code Grant (Section 4.1) * Refresh Token Grant (Section 6) * Error response format (Section 5.2) * βœ… **RFC 7636** - Proof Key for Code Exchange (PKCE) * Required for all Authorization Code flows * SHA256 challenge method support * βœ… **RFC 7009** - Token Revocation * Standardized revocation endpoint * Success response regardless of token validity * βœ… **RFC 6750** - Bearer Token Usage * Authorization header format * Cache control headers #### Audit Logging Comprehensive audit trail for all OAuth operations: * Token requests (all grant types) * Authorization requests and approvals/denials * Token revocations * Failed authentication attempts * Includes client ID, IP address, timestamps, and outcomes #### Error Handling Standard OAuth 2.0 error responses: **Authorization Errors** (redirect to client): * `access_denied` - User denied authorization * `invalid_scope` - Requested scopes not allowed * `server_error` - Internal server error **Token Endpoint Errors** (JSON response): * `invalid_request` - Missing or malformed parameters * `invalid_client` - Invalid client credentials * `invalid_grant` - Invalid/expired authorization code or refresh token * `unsupported_grant_type` - Grant type not supported All errors include descriptive `error_description` for debugging. #### CORS Support Full CORS support for browser-based applications: * Preflight request handling (OPTIONS) * Configurable allowed origins * Credential support for secure cookie handling * Headers: `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers` #### Migration **No action required for existing integrations:** * All existing clients default to **Confidential** type * Existing Client Credentials flow continues unchanged * Existing authentication patterns remain fully supported **New capabilities available:** * Request Authorization Code flow access for user-facing integrations * Request Public client type for mobile/SPA applications * Contact BuildPass support to enable new features #### Documentation Complete documentation available: * [Authentication Overview](/features/authentication) - Client types and Client Credentials flow * [OAuth 2.0 Authorization Code Flow](/features/oauth-authorization-code) - User authorization guide * Example code for multiple languages and platforms * Security best practices for credential storage * Platform-specific integration guides *** ### November 19, 2025 - Multi-Region Database Support We've added multi-region database routing to support clients in both Australia and the United States. #### What's New * **Region-based Routing**: Route API requests to your client's regional tenant using the `X-BuildPass-Region-Id` header * **Supported Regions**: * `au1` - Australia (Sydney) - **Default** * `us1` - United States (Ohio) #### Usage Include the region header in your API requests to connect to your client's tenant: ```bash theme={null} curl -X GET "https://api.buildpass.global/builders" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "X-BuildPass-Api-Version: v1" \ -H "X-BuildPass-Region-Id: us1" ``` Each client's BuildPass account is hosted in one region. Store the region identifier alongside their OAuth credentials in your integration. #### Migration No migration is required for existing Australian clients: * **Australian clients**: Continue without the header (defaults to `au1`) or explicitly add `X-BuildPass-Region-Id: au1` * **United States clients**: Add `X-BuildPass-Region-Id: us1` to all requests for these clients #### Best Practices * Store each client's region identifier with their credentials * Use the same region for token generation and all API requests for a client * When onboarding new clients, confirm their region with BuildPass For detailed documentation, see [Multi-Region Support](/features/multi-region). *** ### November 11, 2025 - New Inductions API endpoints We've added new endpoints to help you integrate with BuildPass induction data: #### Inductions API New endpoints for accessing induction records: * **[GET /subcontractors/\/inductions](/api-reference/subcontractors/inductions/list)** - Get all inductions for workers associated with a subcontractor * Filter by project ID, status, and type * Supports pagination with offset/limit * Returns induction details including type, status, worker, subcontractor * **[GET /builders/\/projects/\/inductions](/api-reference/builders/projects/inductions/list)** - Get all inductions for a project * Filter by status * Supports pagination with offset/limit * Returns induction details including type, status, and worker information * **[GET /builders/\/projects/\/inductions/\](/api-reference/builders/projects/inductions/get)** - Get a specific induction * Supports lookup by **project-specific identifier** (e.g. `5`) or **induction ID** (e.g. `ind_abc123`) * Automatically returns latest version when version history exists * Returns full induction details with worker, subcontractor, project, and responses These endpoints require the `read:inductions` scope and follow the same authentication patterns as other API endpoints. *** ### January 15, 2025 - Subcontractor endpoints improvements Enhanced performance and reliability for subcontractor status data: * **[GET /subcontractors](/api-reference/subcontractors/list)** - List subcontractors * Subcontractor statuses are now properly filtered based on the `projectId` query parameter when provided * Fixed an issue that caused duplicate statuses to appear in responses * **[GET /subcontractors/\](/api-reference/subcontractors/get)** - Get subcontractor * Added support for the `projectId` query parameter to retrieve project-specific status information *** ### June 25, 2025 - OAuth 2.0 authentication enhancements We've enhanced our authentication system to more effectively comply with the OAuth 2.0 standards: #### New features * **HTTP Basic Authentication**: You can now authenticate using HTTP Basic Authentication in addition to the existing request body method * Pass client credentials via the `Authorization: Basic ` header * Credentials should be Base64-encoded in the format `client_id:client_secret` * Request body credentials take precedence when both methods are used #### Changes * **Standardized Token Expiration**: The `expires` field has been renamed to `expires_in`. The value of this field has not changed. * **Enhanced Security**: Improved request validation and error handling. #### Migration guide You must ensure your code properly handles the `expires_in` field. This can be used to determine when a new token is necessary. The `expires` field will be maintained until the 25th of September, 2025. *** ### May 26th, 2025 - New API endpoints #### Timesheets API We've added comprehensive timesheet management endpoints to help you integrate with BuildPass timesheet data: * **[GET /timesheets](/api-reference/timesheets/list)** - Retrieve all timesheets for a builder with filtering options * Filter by project, status, and date range * Supports pagination with offset/limit * Returns timesheet details including hours, notes, time types, and cost codes * **[GET /timesheets/\](/api-reference/timesheets/get)** - Get a specific timesheet by ID * Includes associated profile and project information * Full timesheet details with approval status * **[GET /timesheets/time-types](/api-reference/timesheets/timeTypes)** - Get configured time types for a builder * Returns available time categories (e.g., "Regular Hours", "Overtime", "Annual Leave") * **[GET /timesheets/cost-codes](/api-reference/timesheets/costCodes)** - Get configured cost codes for a builder * Returns project cost codes for timesheet categorization #### SWMS (Safe Work Method Statements) API New endpoints for accessing SWMS documents: * **[GET /subcontractors/\/swms](/api-reference/subcontractors/swms/list)** - Get all SWMS documents for a subcontractor * Filter by project ID and review status * Supports pagination * Returns document metadata and review status * **[GET /subcontractors/\/swms/\](/api-reference/subcontractors/swms/get)** - Get a specific SWMS document * Includes document URL for download * Shows current review status and approval state These endpoints require appropriate scopes (`read:timesheets` and `read:swms`) and follow the same authentication patterns as other API endpoints. *** ## Need help? If you have questions about these changes or need assistance with migration, please contact our support team. # Authentication Source: https://developer.buildpass.global/features/authentication To interact with the BuildPass API, you need to authenticate using OAuth 2.0. The BuildPass API uses **OAuth 2.0** for authentication, fully compliant with RFC 6749. We support two authentication flows: ## Authentication Flows ### Client Credentials Grant (Server-to-Server) For **server-to-server integrations** without user involvement, use the Client Credentials flow. This is ideal for backend services that need to access BuildPass data programmatically. πŸ‘‰ **This page documents the Client Credentials flow.** ### Authorization Code Grant (User Authorization) For **applications that need user consent** and access to data on behalf of specific builders, use the Authorization Code flow with PKCE. Learn about user authorization with PKCE for integrator applications. *** ## Client Types BuildPass supports two types of OAuth 2.0 clients, each designed for different security requirements: ### Confidential Clients **Confidential clients** can securely store credentials and are required to authenticate with a `client_secret`. **Best for:** * Backend services and servers * Server-to-server integrations * Applications running in secure, controlled environments * Services where credentials can be kept private **Authentication:** Must provide both `client_id` and `client_secret` to obtain access tokens. ### Public Clients **Public clients** cannot securely store credentials (e.g., mobile apps, single-page applications) and can authenticate without a `client_secret`. **Best for:** * Mobile applications (iOS, Android) * Single-page applications (SPAs) * Desktop applications * Browser-based applications **Authentication:** Only requires `client_id`. Must use PKCE (Proof Key for Code Exchange) with the Authorization Code flow for security. Your client type is determined when BuildPass provisions your integration credentials. Contact BuildPass support if you need to change your client type or are unsure which type you have. *** ## Client Credentials Grant This flow provides secure, token-based authentication for server-to-server integrations. **Client Credentials Grant is only available for Confidential Clients.** Public clients must use the [Authorization Code flow with PKCE](/features/oauth-authorization-code). ### Step 1: Obtain Client Credentials You need to have the following client credentials: * `client_id` * `client_secret` These credentials should be provided by BuildPass. If you don't have them, please contact BuildPass support. ### Step 2: Generate an OAuth Token To generate an OAuth token, you need to make a POST request to the `/oauth/token` endpoint with your client credentials. The request body should include the following parameters: * `client_id`: Your client ID. * `client_secret`: Your client secret. * `scope`: The scopes you want to request access to. Available scopes include `read:builders`, `read:subcontractors`, `read:prequalifications`, `read:insurances`, `read:contacts`, `read:swms`, `read:timesheets`, `read:inductions`. * `audience`: The audience for the token. This should be set to `https://api.buildpass.global`. * `grant_type`: The grant type you want to use. This should be set to `client_credentials`. Use `https://api.buildpass.global` as both the OAuth host and token audience for External API integrations. Regional MCP connector hosts use a different OAuth resource model and are not a replacement for the External API integration audience. Check out the API reference for our OAuth2 token endpoint. #### Example Request ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --data '{ "client_id": "your_client_id", "client_secret": "your_client_secret", "scope": "read:builders read:subcontractors read:prequalifications read:insurances", "audience": "https://api.buildpass.global", "grant_type": "client_credentials" }' ``` #### Alternative: HTTP Basic Authentication You can also provide client credentials via HTTP Basic Authentication instead of the request body: ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic base64(client_id:client_secret)' \ --data '{ "scope": "read:builders read:subcontractors", "audience": "https://api.buildpass.global", "grant_type": "client_credentials" }' ``` #### Form Data Support The endpoint also supports `application/x-www-form-urlencoded` content type: ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data 'client_id=your_client_id&client_secret=your_client_secret&scope=read:builders&audience=https://api.buildpass.global&grant_type=client_credentials' ``` #### Response Format The token response follows OAuth 2.0 standards: ```json theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600, "expires": 3600 // deprecated, please use expires_in, "scope": "read:builders read:subcontractors" } ``` #### Error Responses Error responses follow OAuth 2.0 RFC 6749 standards: ```json theme={null} { "error": "invalid_client", "error_description": "Invalid client credentials" } ``` Common error codes: * `invalid_request`: Missing or malformed request parameters * `invalid_client`: Invalid client credentials * `invalid_scope`: Requested scopes are invalid for the audience * `unsupported_grant_type`: Grant type not supported ### Step 3: Use the Access Token Once you have the access token, include it in the Authorization header of your API requests as a Bearer token. #### Example Authorization Header ``` Authorization: Bearer YOUR_ACCESS_TOKEN ``` ## OAuth 2.0 Compliance Features Our implementation is fully compliant with OAuth 2.0 standards: ### RFC 6749 - OAuth 2.0 Authorization Framework * βœ… **Client Credentials Grant** (Section 4.4) * βœ… **Standard Token Response Format** (Section 5.1) * βœ… **Standard Error Response Format** (Section 5.2) * βœ… **Client Authentication Methods** (Section 2.3.1) ### RFC 6750 - Bearer Token Usage * βœ… **Authorization Request Header Field** (Section 2.1) * βœ… **Cache Control Headers** (Section 3) ### Additional Security Features * βœ… **JWT Access Tokens** with HMAC-SHA256 signing * βœ… **Unique Token IDs** (jti claim) for token tracking * βœ… **Encrypted Client Secret Storage** * βœ… **Audience-Specific Scope Validation** * βœ… **Comprehensive Audit Logging** ### Token Management * **Token Lifetime**: 1 hour (3600 seconds) * **Token Format**: JSON Web Token (JWT) * **Signing Algorithm**: HMAC-SHA256 * **Security Headers**: Cache-Control: no-store, Pragma: no-cache ## Token Security Best Practices ### Credential Storage **Critical Security Requirements:** 1. **Encrypt client secrets at rest** - Never store in plain text or environment variables visible in logs 2. **Use secure credential management** - Consider using secret managers (AWS Secrets Manager, HashiCorp Vault, etc.) 3. **Encrypt access tokens at rest** - Use your platform's secure storage 4. **Never log credentials or tokens** - Treat them as sensitive data 5. **Rotate credentials periodically** - Contact BuildPass support for credential rotation ### Token Handling ```javascript theme={null} // βœ… GOOD: Secure credential storage (Node.js example) const AWS = require('aws-sdk'); const secretsManager = new AWS.SecretsManager(); async function getCredentials() { const secret = await secretsManager.getSecretValue({ SecretId: 'buildpass/client-credentials' }).promise(); return JSON.parse(secret.SecretString); } // ❌ BAD: Never do this const CLIENT_SECRET = process.env.CLIENT_SECRET; // Visible in logs console.log('Secret:', CLIENT_SECRET); // Never log secrets! ``` ### Access Token Storage For applications that cache access tokens: ```javascript theme={null} // βœ… GOOD: In-memory storage with expiration tracking class TokenManager { constructor() { this.token = null; this.expiresAt = null; } async getToken() { if (this.token && Date.now() < this.expiresAt) { return this.token; } return await this.refreshToken(); } async refreshToken() { const response = await fetchNewToken(); this.token = response.access_token; this.expiresAt = Date.now() + (response.expires_in * 1000); return this.token; } } // ❌ BAD: Never store tokens in files or databases without encryption fs.writeFileSync('token.txt', accessToken); // Insecure! ``` ### Network Security 1. **Always use HTTPS** - BuildPass API only accepts HTTPS connections 2. **Validate TLS certificates** - Don't disable certificate validation 3. **Use Basic Auth header** - Preferred method for client credentials 4. **Don't include credentials in URLs** - Use headers or request body ### Monitoring and Auditing BuildPass provides comprehensive audit logging: * All token requests are logged with client ID and IP address * Failed authentication attempts are tracked * Unusual patterns trigger alerts We recommend: * Monitor your token usage patterns * Set up alerts for failed authentication attempts * Regularly review access logs * Investigate unexpected token requests # Filtering Source: https://developer.buildpass.global/features/filtering The BuildPass API allows you to filter results using query parameters in your GET requests. Here’s some examples of how you can filter subcontractors by project and document types by their category. Please see API reference for more information. ### Filtering Subcontractors by Project To filter subcontractors for a specific project, use the `projectId` query parameter in your GET request to `/subcontractors`. #### Example Request ``` GET /subcontractors?projectId=proj_clgbsb90b001qjy0f0eo1hspp HTTP/1.1 X-BuildPass-Api-Version: v1 X-BuildPass-Builder-Id: buil_clgbsb90b001qjy0f0eo1hspp Authorization: Bearer YOUR_ACCESS_TOKEN ``` ### Filtering Prequalifications by Status To filter prequalifications by their status, use the `status` query parameter in your GET request to `/subcontractors/{id}/prequalifications`. #### Example Request ``` GET /subcontractors/sub_clgbsb90b001qjy0f0eo1hspp/prequalifications?status=APPROVED HTTP/1.1 X-BuildPass-Api-Version: v1 Authorization: Bearer YOUR_ACCESS_TOKEN ``` # Multi-region Source: https://developer.buildpass.global/features/multi-region Route your API requests to our Australia or United States data centres ## Overview BuildPass operates separate tenant environments in Australia and the United States. Each of your client's BuildPass accounts is hosted in one of these regions. Use the appropriate region identifier to connect to each client's tenant. ## Available regions | Region | Region Code | Location | | ------------------- | ---------------- | ------------------- | | Australia (Default) | `au1` or omitted | Sydney, Australia | | United States | `us1` | Ohio, United States | ## Usage ### Setting the region To route your requests to a specific client's region, include the `X-BuildPass-Region-Id` header in your API requests: ```bash theme={null} curl -X GET "https://api.buildpass.global/builders" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "X-BuildPass-Api-Version: v1" \ -H "X-BuildPass-Region-Id: us1" ``` ### Default behavior If the `X-BuildPass-Region-Id` header is: * **Not provided**: Defaults to Australia (`au1`) * **Unrecognized value**: Defaults to Australia (`au1`) This ensures backward compatibility with existing integrations. External API integrations should continue to use `https://api.buildpass.global` with the region header or default Australia routing described here. Regional OAuth hosts such as `https://api.au.buildpass.global` are for BuildPass AI MCP connector setup, where MCP clients cannot reliably provide BuildPass region headers. ## How it works Simply include the `X-BuildPass-Region-Id` header in your API requests to connect to your client's tenant. Each client's BuildPass account is hosted in either Australia or the United Statesβ€”use the corresponding region code to access their data. ## Examples ### OAuth token request (US region) ```bash theme={null} curl -X POST "https://api.buildpass.global/oauth/token" \ -H "Content-Type: application/json" \ -H "X-BuildPass-Api-Version: v1" \ -H "X-BuildPass-Region-Id: us1" \ -d '{ "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET", "grant_type": "client_credentials", "scope": "read:builders", "audience": "https://api.buildpass.global" }' ``` ### Australia region (default) If you don't specify a region, requests automatically use the Australia data centre: ```bash theme={null} curl -X GET "https://api.buildpass.global/builders" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "X-BuildPass-Api-Version: v1" ``` ### United States region To use the US data centre, add the region header: ```bash theme={null} curl -X GET "https://api.buildpass.global/builders" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "X-BuildPass-Api-Version: v1" \ -H "X-BuildPass-Region-Id: us1" ``` ## Need help? If you're unsure which region a client's account is hosted in or have questions about implementing multi-region support in your integration, please contact your BuildPass account manager or reach out to our support team at [support@buildpass.com.au](mailto:support@buildpass.com.au). # OAuth 2.0 Authorization Code Flow Source: https://developer.buildpass.global/features/oauth-authorization-code Secure user authorization with PKCE for integrator applications BuildPass supports **OAuth 2.0 Authorization Code Grant with PKCE** (Proof Key for Code Exchange) for integrator applications that need to access builder data on behalf of users. This flow is ideal for third-party applications that require user consent. ## Overview The Authorization Code flow allows your application to: 1. Direct users to BuildPass for authentication and consent 2. Receive an authorization code after user approval 3. Exchange the code for access and refresh tokens 4. Use access tokens to make API requests on behalf of the user 5. Use refresh tokens to obtain new access tokens ## When to Use This Flow Use the Authorization Code flow when: * Your application needs to access BuildPass data **on behalf of a specific user/builder** * You want users to explicitly authorize your application * You need long-lived access via refresh tokens * You're building a mobile app, SPA, or desktop application (public clients) * You're building a backend application that requires user authorization (confidential clients) For server-to-server integrations without user involvement, use the [Client Credentials flow](/features/authentication) instead. External API integrations authorize against `https://api.buildpass.global` and receive tokens for the `https://api.buildpass.global` audience. BuildPass AI MCP connectors use regional OAuth and MCP resource URLs, which are separate from the External API integration audience. ## Client Types and Authentication This flow works with both **Confidential** and **Public** clients: ### Confidential Clients Backend applications that can securely store a `client_secret`. Must authenticate with both `client_id` and `client_secret` when exchanging codes for tokens. **Examples:** Web servers, backend services ### Public Clients Applications that cannot securely store secrets. Authenticate with only `client_id` and rely on PKCE for security. **Examples:** Mobile apps, single-page applications, desktop apps For public BuildPass AI MCP clients that request `execute:ai_agent_tools`, loopback callback hosts are treated as aliases during authorization-code exchange. This allows native MCP clients to authorize with `http://127.0.0.1:/callback` and exchange the code with `http://localhost:/callback`, or the reverse. The protocol, path, query string, and non-loopback host still need to match. **PKCE is required for all authorization requests**, regardless of client type. This provides an additional layer of security beyond traditional OAuth 2.0. ## Security Features BuildPass implements industry-standard security measures: * βœ… **PKCE (RFC 7636)** - Required for all authorization requests * βœ… **State Parameter** - Prevents CSRF attacks * βœ… **Authorization Code Reuse Protection** - Codes are single-use only * βœ… **Refresh Token Rotation** - New refresh token issued on each use * βœ… **Token Revocation** - RFC 7009 compliant revocation endpoint * βœ… **Rate Limiting** - Protects against abuse * βœ… **Comprehensive Audit Logging** - All authorization events tracked ## Flow Diagram ```mermaid theme={null} sequenceDiagram participant App as Your Application participant Browser as User Browser participant BP as BuildPass participant API as BuildPass API App->>App: Generate code_verifier & code_challenge App->>Browser: Redirect to /oauth/authorize Browser->>BP: Authorization request (with PKCE) BP->>Browser: Show consent screen Browser->>BP: User approves BP->>Browser: Redirect with authorization code Browser->>App: Authorization code received App->>API: POST /oauth/token (code + code_verifier) API->>App: access_token + refresh_token App->>API: API requests with access_token ``` ## Step-by-Step Implementation ### Step 1: Generate PKCE Values Before redirecting users, generate a code verifier and challenge: ```javascript theme={null} // Generate random code_verifier (43-128 characters) function generateCodeVerifier() { const array = new Uint8Array(32); crypto.getRandomValues(array); return base64UrlEncode(array); } // Create code_challenge from verifier using SHA256 async function generateCodeChallenge(verifier) { const encoder = new TextEncoder(); const data = encoder.encode(verifier); const hash = await crypto.subtle.digest("SHA-256", data); return base64UrlEncode(new Uint8Array(hash)); } function base64UrlEncode(buffer) { return btoa(String.fromCharCode(...buffer)) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } ``` Store the `code_verifier` securely in your session - you'll need it in Step 3! ### Step 2: Redirect User to Authorization Endpoint Redirect the user to BuildPass for authorization: ``` GET https://api.buildpass.global/oauth/authorize ``` **Required Parameters:** | Parameter | Description | | ----------------------- | ------------------------------------------------------------------------------------ | | `client_id` | Your application's client ID | | `redirect_uri` | Registered callback URL where BuildPass will send the authorization code | | `response_type` | Must be `code` | | `scope` | Space-separated list of requested scopes (e.g., `read:builders read:subcontractors`) | | `code_challenge` | Base64-URL-encoded SHA256 hash of your code\_verifier | | `code_challenge_method` | Must be `S256` (SHA256) | | `state` | Random string to prevent CSRF attacks | **Optional Parameters:** | Parameter | Description | | ------------ | -------------------------------------------------------------- | | `builder_id` | Pre-select a specific builder (if user has access to multiple) | You do **not** need to send `X-BuildPass-Api-Version` for `/oauth/authorize`. Browser redirects cannot include custom headers, so this endpoint defaults to API version `v1` when omitted. **Example Authorization URL:** ```javascript theme={null} const authUrl = new URL("https://api.buildpass.global/oauth/authorize"); authUrl.searchParams.set("client_id", "your_client_id"); authUrl.searchParams.set("redirect_uri", "https://yourapp.com/callback"); authUrl.searchParams.set("response_type", "code"); authUrl.searchParams.set("scope", "read:builders read:subcontractors"); authUrl.searchParams.set("code_challenge", codeChallenge); authUrl.searchParams.set("code_challenge_method", "S256"); authUrl.searchParams.set("state", randomState); // Redirect user window.location.href = authUrl.toString(); ``` ### Step 3: Handle the Authorization Callback After user approval, BuildPass redirects back to your `redirect_uri` with: **Success Response:** ``` https://yourapp.com/callback?code=abc123&state=xyz789 ``` **Error Response:** ``` https://yourapp.com/callback?error=access_denied&error_description=User+denied+consent&state=xyz789 ``` Always validate the `state` parameter matches what you sent to prevent CSRF attacks! ### Step 4: Exchange Authorization Code for Tokens Exchange the authorization code for access and refresh tokens: **For Confidential Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic base64(client_id:client_secret)' \ --data '{ "grant_type": "authorization_code", "code": "received_authorization_code", "redirect_uri": "https://yourapp.com/callback", "code_verifier": "your_stored_code_verifier" }' ``` **For Public Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --data '{ "grant_type": "authorization_code", "client_id": "your_client_id", "code": "received_authorization_code", "redirect_uri": "https://yourapp.com/callback", "code_verifier": "your_stored_code_verifier" }' ``` **Required Parameters:** | Parameter | Description | | --------------- | ----------------------------------------------------- | | `grant_type` | Must be `authorization_code` | | `code` | Authorization code from callback | | `redirect_uri` | Must match the original request | | `code_verifier` | Original code verifier used to generate the challenge | | `client_id` | Required for public clients (in request body) | **Client Authentication:** **Confidential Clients** - Provide credentials via **HTTP Basic Authentication** (recommended): ``` Authorization: Basic base64encode(client_id:client_secret) ``` Or in the request body (alternative): ```json theme={null} { "client_id": "your_client_id", "client_secret": "your_client_secret", ... } ``` **Public Clients** - Include only `client_id` in the request body: ```json theme={null} { "client_id": "your_client_id", ... } ``` Public clients must **never** include a `client_secret`. Security for public clients relies entirely on PKCE and the registered redirect URIs. **Success Response:** ```json theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "550e8400-e29b-41d4-a716-446655440000", "token_type": "Bearer", "expires_in": 3600, "scope": "read:builders read:subcontractors" } ``` ### Step 5: Fetch the authorised user identity After exchanging the authorization code, call `GET /me` with the access token to retrieve the BuildPass user identity and the builders they consented for. The `/me` response now includes signed asset URLs you can use directly in your integration: * `profilePictureUrl` - signed URL for the authorised user's BuildPass profile photo, if one is configured * `memberships[].builderLogoUrl` - signed URL for each consented builder's company logo, if one is configured These URLs are especially useful when you want to mirror a connected user's BuildPass avatar or company branding into your own product. **Token Details:** * **access\_token**: Use this to make API requests (lifetime: **1 hour**) * **refresh\_token**: Use this to get new access tokens (lifetime: **30 days**) * **expires\_in**: Access token lifetime in seconds (3600 = 1 hour) * **scope**: Granted scopes (may differ from requested scopes) ### Step 6: Use the Access Token Include the access token in API requests: ```bash theme={null} curl --request GET \ --url https://api.buildpass.global/builders \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` ### Step 7: Refresh the Access Token When the access token expires, use the refresh token to get a new one: **For Confidential Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic base64(client_id:client_secret)' \ --data '{ "grant_type": "refresh_token", "refresh_token": "your_refresh_token" }' ``` **For Public Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/token \ --header 'Content-Type: application/json' \ --data '{ "grant_type": "refresh_token", "client_id": "your_client_id", "refresh_token": "your_refresh_token" }' ``` **Response:** ```json theme={null} { "access_token": "new_access_token", "refresh_token": "new_refresh_token", "token_type": "Bearer", "expires_in": 3600, "scope": "read:builders read:subcontractors" } ``` **Refresh Token Rotation:** BuildPass automatically rotates refresh tokens. The old refresh token is revoked and a new one is issued. Always store the new `refresh_token` from the response. ### Step 8: Revoke Tokens (Optional) When a user disconnects your integration or you need to invalidate tokens: **For Confidential Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/revoke \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic base64(client_id:client_secret)' \ --data '{ "token": "token_to_revoke", "token_type_hint": "refresh_token" }' ``` **For Public Clients:** ```bash theme={null} curl --request POST \ --url https://api.buildpass.global/oauth/revoke \ --header 'Content-Type: application/json' \ --data '{ "client_id": "your_client_id", "token": "token_to_revoke", "token_type_hint": "refresh_token" }' ``` **Parameters:** | Parameter | Description | | ----------------- | --------------------------------------------- | | `token` | The token to revoke (access or refresh token) | | `token_type_hint` | Optional: `access_token` or `refresh_token` | Per RFC 7009, the endpoint returns `200 OK` regardless of whether the token was found, preventing token scanning attacks. ## Available Scopes Request only the scopes your application needs: | Scope | Description | | ------------------------ | --------------------------------- | | `read:builders` | Access builder information | | `read:subcontractors` | Access subcontractor information | | `read:projects` | Access project information | | `read:insurances` | Access insurance certificates | | `read:prequalifications` | Access prequalification documents | | `read:contacts` | Access contact information | | `read:swms` | Access SWMS documents | | `read:timesheets` | Access timesheet data | | `read:inductions` | Access induction records | ## Scope Changes and Re-Authorization **Important:** If your application's allowed scopes change, users must **re-authorize** your application to grant the new permissions. When you request different scopes: 1. Users will see a new consent screen showing the updated permissions 2. Previous authorization codes and tokens remain valid with their original scopes 3. New tokens will include the updated scopes We do not currently support incremental consent (automatically upgrading existing tokens with new scopes). ## Token Security Best Practices ### Storage Guidelines **Critical Security Requirements:** **For All Clients:** 1. **Encrypt tokens at rest** - Use your platform's secure storage 2. **Never log tokens** - Treat them as sensitive credentials 3. **Use HTTPS only** - All communication must be over TLS 4. **Validate redirect URIs** - Ensure they match registered URIs exactly **For Confidential Clients:** 1. **Protect client\_secret** - Store securely using secret managers (AWS Secrets Manager, HashiCorp Vault, etc.) 2. **Never expose secrets client-side** - Keep credentials server-side only 3. **Use HTTP Basic Auth** - Preferred over body parameters 4. **Rotate credentials periodically** - Contact BuildPass for rotation **For Public Clients:** 1. **Never store tokens in browser localStorage or sessionStorage** - Vulnerable to XSS attacks 2. **Use platform-specific secure storage:** * iOS: Keychain * Android: KeyStore * Desktop: OS-specific credential managers 3. **Implement proper PKCE** - Generate cryptographically random verifiers 4. **Validate state parameter** - Prevent CSRF attacks 5. **Use short-lived in-memory storage** where possible for access tokens ### Token Handling ```javascript theme={null} // βœ… GOOD: Secure token storage (Node.js example) const encryptedToken = encrypt(accessToken, encryptionKey); await secureDb.store("access_token", encryptedToken); // ❌ BAD: Never do this localStorage.setItem("access_token", accessToken); // Vulnerable to XSS! console.log("Token:", accessToken); // Never log tokens! ``` ### Detecting Token Expiration ```javascript theme={null} // Check expires_in from token response const expiresAt = Date.now() + response.expires_in * 1000; // Before making API requests: if (Date.now() >= expiresAt) { // Token expired, refresh it await refreshAccessToken(); } ``` ## Error Responses All OAuth errors follow RFC 6749 standards: ```json theme={null} { "error": "invalid_grant", "error_description": "Authorization code has expired" } ``` **Common Error Codes:** | Error Code | Description | HTTP Status | | ----------------- | ---------------------------------- | ----------- | | `invalid_request` | Missing or malformed parameters | 400 | | `invalid_client` | Invalid client credentials | 401 | | `invalid_grant` | Invalid/expired authorization code | 400 | | `invalid_scope` | Requested scopes not allowed | 400 | | `access_denied` | User denied authorization | 400 | | `server_error` | Internal server error | 500 | ## Rate Limits OAuth endpoints are rate-limited to prevent abuse: | Endpoint | Limit | Window | | ------------------ | ----------- | ---------- | | `/oauth/authorize` | 30 requests | 10 seconds | | `/oauth/token` | 60 requests | 10 seconds | | `/oauth/revoke` | 30 requests | 10 seconds | Rate limit headers are included in responses: ``` X-RateLimit-Limit: 60 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1640000000 Retry-After: 5 ``` ## Authorization Code Reuse Protection **Security Feature:** Authorization codes can only be used **once**. Attempting to reuse a code will: 1. Return an `invalid_grant` error 2. **Revoke all refresh tokens** associated with that authorization 3. Require the user to re-authorize your application This protects against authorization code interception attacks. ## Testing Your Integration ### Step-by-Step Checklist * [ ] Generate valid PKCE code\_verifier and code\_challenge * [ ] Construct authorization URL with all required parameters * [ ] Implement state parameter validation in callback * [ ] Handle both success and error callbacks * [ ] Exchange authorization code for tokens within 10 minutes * [ ] Store refresh token securely * [ ] Implement token refresh before expiration * [ ] Handle token revocation * [ ] Test scope permission boundaries * [ ] Test authorization code reuse (should fail) * [ ] Test expired authorization code (should fail) * [ ] Test mismatched redirect\_uri (should fail) * [ ] Test invalid code\_verifier (should fail) ### Example Error Scenarios **Expired Authorization Code:** ```json theme={null} { "error": "invalid_grant", "error_description": "Authorization code has expired" } ``` **Invalid PKCE Verifier:** ```json theme={null} { "error": "invalid_grant", "error_description": "Invalid PKCE verifier" } ``` **Authorization Code Reused:** ```json theme={null} { "error": "invalid_grant", "error_description": "Authorization code has already been used" } ``` ## RFC Compliance BuildPass OAuth implementation is fully compliant with: * βœ… **RFC 6749** - OAuth 2.0 Authorization Framework * βœ… **RFC 7636** - Proof Key for Code Exchange (PKCE) * βœ… **RFC 7009** - Token Revocation * βœ… **RFC 6750** - Bearer Token Usage ## Support For questions or issues with OAuth integration: * Email: [support@buildpass.com.au](mailto:support@buildpass.com.au) * Documentation: [https://docs.buildpass.global](https://docs.buildpass.global) Need help with your integration? Our team is here to assist with implementation questions and troubleshooting. # Pagination Source: https://developer.buildpass.global/features/pagination The BuildPass API supports pagination to help you manage large sets of data. Use the `offset` and `limit` query parameters to paginate through results. ### Using Offset and Limit * `offset`: The number of items to skip before starting to collect the result set i.e page size. * `limit`: The number of items to return (max `25`). ### Example Request To get the second page of subcontractors, assuming a page size of 25: ``` GET /subcontractors?offset=0&limit=25 HTTP/1.1 X-BuildPass-Api-Version: v1 Authorization: Bearer YOUR_ACCESS_TOKEN ``` ### Example Response Structure The response will include a `meta` object with pagination details. ```json theme={null} { "data": [ { "id": "sub_clgbsb90b001qjy0f0eo1hspp", "createdAt": "2023-10-03T23:19:35.771Z", "updatedAt": "2023-10-03T23:19:35.771Z", "name": "Andrews Brick Laying", ... } ], "meta": { "totalCount": 100, "totalPages": 4, "offset": 0, "limit": 25 } } ``` # Rate limiting Source: https://developer.buildpass.global/features/rate-limiting The BuildPass API uses rate limiting protection. Rate limiting protects the API from abuse and ensure fair usage across all clients. The rate limit is set to **100 requests every 10 seconds** per IP address. When a rate limit is exceeded, the API will return a `429 Too Many Requests` response. An example response when the rate limit is exceeded: ```HTTP theme={null} HTTP/1.1 429 Too Many Requests Content-Type: application/json { "error": { "message": "Rate limit exceeded. Please try again later." } } ``` If you encounter rate limiting issues, please: 1. Implement exponential backoff in your retry logic 2. Cache responses where appropriate to reduce API calls 3. Contact support if you need higher rate limits for your use case # Versioning Source: https://developer.buildpass.global/features/versioning The BuildPass API supports versioning to ensure that your integration remains stable even as the API evolves. You must specify which version of the API you want to use at an endpoint level, helping to avoid breaking changes. ### Specifying the API Version To specify the API version, include the `X-BuildPass-Api-Version` header in your requests. Currently, the only available version is `v1`. If the `X-BuildPass-Api-Version` header is not included in your request, the API will return a bad request error. OAuth endpoints (`/oauth/authorize`, `/oauth/token`, `/oauth/revoke`) default to `v1` when the version header is omitted. This enables browser redirects for authorization flows where custom headers cannot be set. ### Example request When making a request, include the `X-BuildPass-Api-Version` header set to `v1`. ``` GET /builders HTTP/1.1 Authorization: Bearer YOUR_ACCESS_TOKEN X-BuildPass-Api-Version: v1 ``` ### Checking available versions To find out the available API versions and their respective features, refer to the API reference or contact BuildPass support for the latest information. # Introduction Source: https://developer.buildpass.global/introduction BuildPass API Documentation ## Get started To get started, you will need to reach out to the BuildPass team to get your client ID and client secret, which you can then use to generate an OAuth token. ## API features Learn how to generate an OAuth2 token to authenticate your requests. Use filters to return a subset of data in our list queries. Learn how to paginate through our list queries. Learn how to version your requests to ensure compatibility. Learn how we rate limit our requests to prevent abuse. View the latest changes and improvements to the BuildPass API. ## Start integrating Once you have your client ID and client secret, you can generate an authentication token and begin to integrate with the BuildPass API. List the builders you have access to. List the projects for a builder. List meetings for a builder with project, status, and date filters. List gallery photos for a builder and retrieve signed image URLs. List the subcontractors under a builder access to. List insurance documents for a subcontractor. List the prequalifications for a subcontractor. List timesheets for a builder with filtering options. List Safe Work Method Statements for a subcontractor.