Assign a crew member to a project
Adds a Site Crew member to the project's roster (Admin or the project's Site Manager). Idempotent — re-adding is a no-op. Admins are on every project already and can't be rostered.
Adds a Site Crew member to the project's roster (Admin or the project's Site Manager). Idempotent — re-adding is a no-op. Admins are on every project already and can't be rostered.
The per-tenant API key, copied from Settings → API & integrations.
Sent as the x-api-key request header. The key is tenant-scoped and acts
with Admin-equivalent, tenant-wide access.
In: header
Path Parameters
Resource id.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/projects/497f6eca-6276-4993-bfeb-53cbbbba6f08/crew" \ -H "Content-Type: application/json" \ -d '{ "userId": "2c4a230c-5085-4924-a3e1-25fb4fc5965b" }'{ "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8", "userId": "2c4a230c-5085-4924-a3e1-25fb4fc5965b", "assigned": true}{ "error": { "code": "unauthorized", "message": "Missing or invalid API key." }}{ "error": { "code": "read_only", "message": "Your subscription is inactive. This action is read-only." }}{ "error": { "code": "not_found", "message": "Not found." }}{ "error": { "code": "validation", "message": "One or more inputs are invalid.", "fields": { "fieldName": "A message explaining what's wrong with this field." } }}Request a presigned standalone-photo upload URL POST
**Step 1 of the presigned standalone-photo upload** — the no-diary-entry sibling of `.../diary-photos/upload-url`. Validates the declared image (JPG/PNG only) and returns a short-lived, single-use **signed PUT URL** (`uploadUrl`) plus the computed `storagePath`. **The image bytes never travel through this API call.** After this returns, the caller PUTs the raw image bytes directly to `uploadUrl` — out of band — then passes the returned `storagePath` in the `storagePaths` array of `POST /projects/{id}/photos`. No diary entry is involved. Any crew member assigned to the project may upload photos; an Admin/API key is implicitly on every project. Blocked on read-only/archived projects. **Photos must be 2 MB or smaller.** The limit is enforced by Storage on the PUT itself, so an oversized upload fails at that step rather than here — this call only sees the *declared* file. Resize before uploading: 1600px on the long edge is plenty, and is what the FOREMAN app sends.
Create a project POST
Create a new job site. On the Free plan, exceeding the project cap returns `403` (`project_cap`) with an upgrade Checkout link.