Register an uploaded document
**Step 2 of the two-step presigned document upload.** Call this *after* you have PUT the file bytes to the `uploadUrl` from `POST /projects/{id}/documents/upload-url`. Pass the `uploadRef` from step 1 (or the `storagePath` + `kind`) plus the `title` (and `audience` for `kind: info`). Verifies the object actually landed in storage (and re-checks its real size/type against the ≤25 MB, PDF/JPG/PNG cap), then creates the document record. The new document then appears in `GET /documents?projectId={id}`. Reading document metadata stays on the read-only `/documents` collection; this project-scoped route is the upload (write) side. Admin or the project's Site Manager; blocked on read-only/archived projects.
Step 2 of the two-step presigned document upload. Call this after
you have PUT the file bytes to the uploadUrl from
POST /projects/{id}/documents/upload-url. Pass the uploadRef from
step 1 (or the storagePath + kind) plus the title (and audience
for kind: info).
Verifies the object actually landed in storage (and re-checks its real
size/type against the ≤25 MB, PDF/JPG/PNG cap), then creates the document
record. The new document then appears in GET /documents?projectId={id}.
Reading document metadata stays on the read-only /documents collection;
this project-scoped route is the upload (write) side. Admin or the
project's Site Manager; blocked on read-only/archived projects.
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.
Provide either uploadRef (from step 1) or storagePath + kind.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/projects/497f6eca-6276-4993-bfeb-53cbbbba6f08/documents" \ -H "Content-Type: application/json" \ -d '{ "title": "string" }'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8", "title": "string", "storagePath": "string", "uploadedAt": "2019-08-24T14:15:22Z", "uploadedByName": "string", "audience": "all_crew", "kind": "ohs"}{ "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." } }}List a project's document metadata GET
Lists document **metadata** (never the binary) for one project, paginated. `project` is required; `kind` narrows to one library, omitted returns both (OHS first, then Project Information).
Get a signed download URL for a document GET
Returns a short-lived **signed download URL** for the document plus its metadata — the read counterpart of the presigned upload (`/projects/{id}/documents/upload-url`). The file bytes are fetched out of band by GETting `downloadUrl`; they never transit this JSON response. The Project-Information audience rule is enforced: a document the caller may not see returns `404` (indistinguishable from a missing one). `?kind` optionally asserts the library (`ohs`/`info`); a mismatch is `404`.