Skip to main content

Production-ready Python SDK foundation for the Procore REST API.

Project description

Procore SDK

Production-quality Python SDK and automation foundation for the Procore REST API.

The SDK handles configuration, OAuth token refresh, authenticated HTTP requests, pagination, typed response models, structured logging, and attachment downloads for companies, projects, RFIs, and submittals.

Installation

Requires Python 3.12+.

python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -r requirements.txt

Configuration

Copy the example file and fill in real values:

cp .env.example .env

Required variables:

PROCORE_CLIENT_ID=your_client_id
PROCORE_CLIENT_SECRET=your_client_secret
PROCORE_REDIRECT_URI=http://localhost:8080/callback
PROCORE_LOGIN_URL=https://login.procore.com
PROCORE_API_BASE=https://api.procore.com
PROCORE_COMPANY_ID=123456

Secrets, tokens, URLs, and company IDs are never hardcoded in source.

Authentication

Exchange the first authorization code and save the token locally:

from auth.oauth import exchange_authorization_code
from auth.token_manager import TokenManager

token_response = exchange_authorization_code("authorization-code-from-procore")
TokenManager().save_oauth_response(token_response)

After that, SDK clients call:

from auth.token_manager import get_access_token

access_token = get_access_token()

Expired access tokens refresh automatically when a refresh token is available.

CLI Examples

.venv/bin/python app.py companies
.venv/bin/python app.py projects
.venv/bin/python app.py rfis --project 352338
.venv/bin/python app.py rfi --project 352338 --id 102784
.venv/bin/python app.py submittals --project 352338
.venv/bin/python app.py submittal --project 352338 --id 309641
.venv/bin/python app.py download-rfi --project 352338 --id 102784
.venv/bin/python app.py download-submittal --project 352338 --id 309641

The CLI prints nicely formatted JSON. Typed SDK models are serialized with model_dump(mode="json").

SDK Examples

from services import (
    download_rfi_attachments,
    download_submittal_attachments,
    get_rfi,
    get_submittal,
    list_companies,
    list_projects,
    list_rfis,
    list_submittals,
)

companies = list_companies()
projects = list_projects(company_id=123456)

rfis = list_rfis(project_id=352338)
rfi = get_rfi(project_id=352338, rfi_id=102784)
first_attachment_url = rfi.questions[0].attachments[0].url

submittals = list_submittals(project_id=352338)
submittal = get_submittal(project_id=352338, submittal_id=309641)

All typed models can be serialized back to JSON:

json_payload = rfi.model_dump(mode="json")
json_string = rfi.model_dump_json()

Downloading Attachments

RFI attachments are read from:

questions[].attachments[].url

Submittal attachments are read from:

attachments[].url

Download from services:

rfi_files = download_rfi_attachments(project_id=352338, rfi_id=102784)
submittal_files = download_submittal_attachments(
    project_id=352338,
    submittal_id=309641,
)

The shared file service supports safe filenames, streaming writes, retries, progress logging, batch downloads, and skip-existing behavior by default.

from services.files import FileDownloadService

files = FileDownloadService().download_attachments(
    attachments,
    "downloads/custom",
    fallback_prefix="attachment",
    overwrite=False,
)

Pagination

Collection service methods use ProcoreClient.get_all(), which follows Procore pagination headers automatically. Business logic should call the service method or get_all() and should not manually request page 2.

Logging

The SDK writes structured logs to:

logs/sdk.log
logs/errors.log

API request logs include method, endpoint, response status, elapsed time, and retry count. Exception logs include stack traces, exception type, request URL, HTTP status, and response body when available.

The logger redacts sensitive keys such as authorization headers, access tokens, refresh tokens, and client secrets.

Architecture

  • auth/: OAuth exchange, token persistence, token refresh
  • core/: configuration, endpoint paths, HTTP client, logging, exceptions
  • models/: Pydantic response models
  • services/: company, project, RFI, submittal, and file services
  • parser/: email parsing utilities for future automation
  • tests/: mocked unit tests with no live Procore dependency

Verified Endpoint Assumptions

  • GET /rest/v1.0/companies
  • GET /rest/v1.0/companies/{company_id}/projects
  • GET /rest/v1.1/projects/{project_id}/rfis
  • GET /rest/v1.1/projects/{project_id}/rfis/{rfi_id}
  • GET /rest/v1.1/projects/{project_id}/submittals
  • GET /rest/v1.1/projects/{project_id}/submittals/{submittal_id}

Troubleshooting

ConfigurationError : Check that .env exists and all required keys are present.

AuthenticationError : Complete the first OAuth code exchange and confirm auth/token_store.json contains a refresh token.

AuthorizationError : Confirm the Procore user has access to the target company/project/resource.

ResourceNotFoundError : Confirm project, RFI, or submittal IDs are correct for the configured company.

Attachment files are not downloading : Check logs/errors.log for HTTP status and response body details. Existing files are skipped unless overwrite=True.

Tests

Run unit tests:

.venv/bin/python -m unittest discover -s tests

Run coverage:

.venv/bin/python -m coverage run -m unittest discover -s tests
.venv/bin/python -m coverage report

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyprocore-1.0.0.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyprocore-1.0.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file pyprocore-1.0.0.tar.gz.

File metadata

  • Download URL: pyprocore-1.0.0.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for pyprocore-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9d86486a5d6771a8896a42618bafeec027f1c5511b99eb3f6b9da1be197a122e
MD5 dfd8ea12a7891edef12f7369beca1cfb
BLAKE2b-256 c717bf976a67788cdcc232a07a9f3b37f3d93398d75f12a62d8eedd199f93c47

See more details on using hashes here.

File details

Details for the file pyprocore-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pyprocore-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for pyprocore-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25cab3754af07cc5d9b695d170397d19fdb69d56f1a2b8b1f4cd8cd13360f559
MD5 03fe6098a9db00a80e2570f736f22e4d
BLAKE2b-256 384994d328aa716d599cbda242c60be48f2da50951b4f2b61c8dbc4dc097cfd9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page