Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions tutorials/tutorial_unified_uploads.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ It is also built with multi-cloud support in mind, so as Procore expands to addi
- **Strict File Size Thresholds:** The system enforces a strict maximum of 100 MiB (104,857,600 bytes) per segment.
- **Checksum Verification:** Segment-level validation will be performed using a mandatory SHA-256 checksum, with an optional MD5 check available for additional verification.
- **24-Hour PDM Tool Association Timeline:** Files uploaded via the Unified File Uploads API must be associated with a PDM tool within 24 hours of upload initialization. If a file is not associated within this timeframe, it will be permanently and automatically deleted from cloud storage with no recovery possible.
- **Status-Driven Interface:** The API relies on a status field (`ready`, `receiving`, `complete`, `available`). Clients should always check that a file's status is `available` before attempting to download it, which indicates all processing and checksum verifications are finished.
- **Status-Driven Interface:** The API relies on a status field (`ready`, `receiving`, `scanning`, `available`, `failed`). Clients should always check that a file's status is `available` before attempting to download it, which indicates that processing and checksum verification — and malware scanning, where enabled — are complete.
- **Standardized ETags:** For uploads, you must explicitly signal completion using an array of `part_etags`.

> **Important — Treat URLs and headers as opaque.**
Expand Down Expand Up @@ -98,6 +98,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proje
"file_size": 2097152,
"content_type": "application/pdf",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"uploader_tool_name": "document_management",
"segments": [
{
"size": 2097152,
Expand All @@ -108,6 +109,8 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proje
}'

```
The `uploader_tool_name` field identifies the Procore tool initiating the upload (for example, `document_management`), and is limited to 64 characters.
It is currently optional but will become required in a future release, so we recommend including it now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajaykumarprocore can you confirm that this will become required in the future?

@ajaykumarprocore ajaykumarprocore Jul 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - this will become required in the future - the wording is accurate. Thank you!!


**Response (201 Created)**

Expand All @@ -118,6 +121,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proje
"file_name": "report.pdf",
"file_size": 2097152,
"content_type": "application/pdf",
"uploader_tool_name": "document_management",
"upload_expires_at": 1773900000,
"segments": [
{
Expand Down Expand Up @@ -191,6 +195,8 @@ curl -X PATCH 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proj
}
```

The `complete` status in the response confirms that all parts have been uploaded and their ETags submitted. The file then moves into server-side processing.

### Step 5 — Poll Until Available (GET)

After completing the upload, poll the upload status until it transitions to `available`.
Expand All @@ -212,6 +218,7 @@ curl -X GET 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/projec
"file_name": "report.pdf",
"sanitized_file_name": "report.pdf",
"content_type": "application/pdf",
"uploader_tool_name": "document_management",
"file_size": 2097152,
"status": "available",
"custom_metadata": {}
Expand Down Expand Up @@ -306,6 +313,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proje
"content_type": "video/mp4",
"sha256": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"md5": "f1e2d3c4b5a6f1e2d3c4b5a6f1e2d3c4",
"uploader_tool_name": "document_management",
"segments": [
{
"size": 6000000,
Expand All @@ -330,6 +338,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/proje
"file_name": "test-video.mp4",
"file_size": 8829449,
"content_type": "video/mp4",
"uploader_tool_name": "document_management",
"upload_expires_at": 1773900000,
"segments": [
{
Expand Down Expand Up @@ -425,6 +434,7 @@ curl -X GET 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/projec
"file_name": "test-video.mp4",
"sanitized_file_name": "test-video.mp4",
"content_type": "video/mp4",
"uploader_tool_name": "document_management",
"file_size": 8829449,
"status": "available",
"custom_metadata": {},
Expand Down Expand Up @@ -460,22 +470,25 @@ curl -X GET 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/projec
"file_name": "report.pdf",
"sanitized_file_name": "report.pdf",
"content_type": "application/pdf",
"uploader_tool_name": "document_management",
"file_size": 2097152,
"status": "complete",
"status": "available",
"error": null,
"custom_metadata": {},
"segments": []
}
}
```

Upload status values include:
The **Get Upload Status (GET)** endpoint returns one of the following:

| Status | Description |
|---|---|
| `ready` | Upload created, waiting for file content |
| `receiving` | Parts are being uploaded (partial ETags submitted) |
| `complete` | All parts uploaded and ETags submitted; returned by the PATCH response |
| `available` | File is fully processed and available for use in Procore |
| `scanning` | The file is being scanned for malware and is not yet available. Appears only when malware scanning is enabled; when it is not, uploads skip this state. |
| `available` | File is fully processed and ready for use in Procore |
| `failed` | The upload could not be completed — for example, the file did not pass its malware scan or the scan could not be run. For malware-scan failures, the response includes an `error` object with `type` and `message`. |

---

Expand All @@ -490,6 +503,7 @@ Upload status values include:
- **Partial progress is supported.** You can submit a PATCH with `null` values in `part_etags` for parts that have not been uploaded yet. Once all values are non-null, the upload is finalized.
- **Uploads expire.** Uploads must be completed and associated with a Procore resource within the expiration window or they will be automatically deleted.
- **The authenticated user owns the upload.** Only the user who created the upload can complete it and use it in subsequent API requests.
- **Files may be scanned for malware before becoming available.** When scanning is enabled, the upload `status` stays `scanning` until the scan completes, then becomes `available`. If a file fails the scan, the status becomes `failed` with an `error` object and the file can't be used. When scanning is not enabled, uploads skip the `scanning` state.

---

Expand Down Expand Up @@ -543,6 +557,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/uploa
"file_size": 2097152,
"content_type": "application/pdf",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"uploader_tool_name": "document_management",
"segments": [
{
"size": 2097152,
Expand All @@ -562,6 +577,7 @@ curl -X POST 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/uploa
"file_name": "report.pdf",
"file_size": 2097152,
"content_type": "application/pdf",
"uploader_tool_name": "document_management",
"upload_expires_at": 1773900000,
"segments": [
{
Expand Down Expand Up @@ -634,6 +650,7 @@ curl -X GET 'https://sandbox.procore.com/rest/v2.1/companies/{company_id}/upload
"file_name": "report.pdf",
"sanitized_file_name": "report.pdf",
"content_type": "application/pdf",
"uploader_tool_name": "document_management",
"file_size": 2097152,
"status": "available",
"custom_metadata": {}
Expand All @@ -646,6 +663,9 @@ Once `status` is `available`, the file can be associated with a company-level re
## Coming Soon

The following capabilities are planned for upcoming releases of the Unified File Upload API:
- **Malware scan** — Automated scanning of uploaded files for malware
- **Malware scan** — Automated scanning of all uploaded files for malware
- **Checksum verification status** — Fields confirming whether server-side checksum verification passed
- **Extended analytics and client metadata** — Additional fields for richer upload telemetry and client identification
- **Required `uploader_tool_name`** — The `uploader_tool_name` field will change from optional to required
- **File-extension allow-list** — Uploads will be restricted to an approved set of file extensions, and uploads with disallowed extensions will be rejected
- **Content-type validation** — Requests where the declared `content_type` does not match the file's actual content will be rejected