/** * Procore API Integration for WORKWAY * * Construction project management integration for 2M+ users worldwide. * Covers projects, RFIs, submittals, daily logs, change orders, and more. * * Zuhandenheit: Contractors don't want "API endpoints" - they want: * - RFIs that get answered * - Submittals that don't hold up the job * - Change orders tracked before they become disputes * - Daily logs that write themselves * * @example * ```typescript * import { Procore } from '@workwayco/integrations/procore'; * * const procore = new Procore({ * accessToken: process.env.PROCORE_ACCESS_TOKEN, * companyId: process.env.PROCORE_COMPANY_ID, * }); * * // Get all projects * const projects = await procore.getProjects(); * * // Get open RFIs for a project * const rfis = await procore.getRFIs({ * projectId: '12345', * status: 'open', * }); * * // Get today's daily logs * const logs = await procore.getDailyLogs({ * projectId: '12345', * date: new Date(), * }); * ``` */ import { ActionResult } from '@workwayco/sdk'; import { BaseAPIClient } from '../core/index.js'; /** * Procore integration configuration * * Authentication: OAuth 2.0 (Authorization Code or Client Credentials) * - Authorization Code: For user-context operations * - Client Credentials (DMSA): For data sync, reports, backend operations */ export interface ProcoreConfig { /** OAuth access token */ accessToken: string; /** Procore company ID (required for most operations) */ companyId: string; /** Environment: 'production' | 'sandbox' | 'sandbox-monthly' */ environment?: 'production' | 'sandbox' | 'sandbox-monthly'; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** OAuth token refresh configuration */ tokenRefresh?: { refreshToken: string; clientId: string; clientSecret: string; onTokenRefreshed: (accessToken: string, refreshToken?: string) => void | Promise; }; } /** * Procore company */ export interface ProcoreCompany { id: number; name: string; is_active: boolean; logo?: { url: string; }; address?: string; city?: string; state_code?: string; zip?: string; country_code?: string; phone?: string; fax?: string; } /** * Procore project */ export interface ProcoreProject { id: number; name: string; display_name?: string; project_number?: string; address?: string; city?: string; state_code?: string; zip?: string; country_code?: string; latitude?: number; longitude?: number; stage?: string; project_type?: { id: number; name: string; }; start_date?: string; completion_date?: string; active: boolean; created_at: string; updated_at: string; photo_url?: string; company?: { id: number; name: string; }; } /** * Procore user */ export interface ProcoreUser { id: number; login: string; name: string; first_name?: string; last_name?: string; email_address?: string; job_title?: string; mobile_phone?: string; business_phone?: string; is_active: boolean; is_employee: boolean; vendor?: { id: number; name: string; }; } /** * Procore RFI (Request for Information) */ export interface ProcoreRFI { id: number; number: string; subject: string; status: 'draft' | 'open' | 'closed'; question?: { body?: string; plain_text_body?: string; }; answer?: { body?: string; plain_text_body?: string; }; due_date?: string; ball_in_court?: ProcoreUser; responsible_contractor?: { id: number; name: string; }; rfi_manager?: ProcoreUser; created_at: string; updated_at: string; closed_at?: string; assignees?: ProcoreUser[]; distribution_list?: ProcoreUser[]; cost_impact?: 'yes' | 'no' | 'tbd' | 'n/a'; cost_impact_amount?: number; schedule_impact?: 'yes' | 'no' | 'tbd' | 'n/a'; schedule_impact_days?: number; spec_section?: { id: number; name: string; }; location?: { id: number; name: string; }; } /** * Procore submittal */ export interface ProcoreSubmittal { id: number; number: string; title: string; description?: string; status: { id: number; name: string; }; submittal_type?: string; spec_section?: { id: number; name: string; }; location?: { id: number; name: string; }; responsible_contractor?: { id: number; name: string; }; received_from?: ProcoreUser; received_date?: string; submit_by_date?: string; due_date?: string; required_on_site_date?: string; revision: number; ball_in_court?: ProcoreUser; approvers?: ProcoreUser[]; created_at: string; updated_at: string; } /** * Procore daily log header */ export interface ProcoreDailyLog { id: number; log_date: string; project_id: number; created_at: string; updated_at: string; weather_conditions?: { temperature_high?: number; temperature_low?: number; conditions?: string; precipitation?: string; }; notes?: string; } /** * Procore manpower log entry */ export interface ProcoreManpowerLog { id: number; daily_log_id: number; vendor?: { id: number; name: string; }; num_workers: number; hours_worked?: number; notes?: string; created_at: string; updated_at: string; } /** * Procore equipment log entry */ export interface ProcoreEquipmentLog { id: number; daily_log_id: number; equipment_description: string; quantity?: number; hours_operated?: number; inspection_type?: string; notes?: string; created_at: string; updated_at: string; } /** * Procore notes log entry */ export interface ProcoreNotesLog { id: number; daily_log_id: number; notes: string; created_at: string; updated_at: string; } /** * Procore change order */ export interface ProcoreChangeOrder { id: number; number: string; title: string; description?: string; status: string; due_date?: string; invoiced_date?: string; paid_date?: string; signed_change_order_received_date?: string; created_at: string; updated_at: string; contract_id?: number; contractor?: { id: number; name: string; }; change_order_request?: { id: number; number: string; }; line_items?: ProcoreChangeOrderLineItem[]; } /** * Procore change order line item */ export interface ProcoreChangeOrderLineItem { id: number; description: string; amount: number; cost_code?: { id: number; full_code: string; name: string; }; } /** * Procore budget line item */ export interface ProcoreBudgetLineItem { id: number; cost_code: { id: number; full_code: string; name: string; }; budget_line_item_type?: string; original_budget_amount: number; approved_change_orders: number; revised_budget: number; committed_costs: number; pending_budget_changes: number; pending_committed_costs: number; projected_cost: number; projected_over_under: number; forecast_to_complete: number; estimated_cost_at_completion: number; } /** * Procore drawing */ export interface ProcoreDrawing { id: number; number: string; title: string; discipline?: string; current_revision?: { id: number; revision: string; revision_date: string; }; drawing_set?: { id: number; name: string; }; created_at: string; updated_at: string; } /** * Procore webhook event */ export interface ProcoreWebhookEvent { resource_name: string; event_type: 'create' | 'update' | 'delete'; resource_id: number; project_id?: number; company_id: number; timestamp: string; metadata?: Record; } export interface GetProjectsOptions { /** Filter by active status */ active?: boolean; /** Filter by stage */ stage?: string; /** Maximum records per page (default: 100, max: 100) */ perPage?: number; /** Page number (default: 1) */ page?: number; } export interface GetRFIsOptions { projectId: string; /** Filter by status */ status?: 'draft' | 'open' | 'closed'; /** Filter by responsible contractor ID */ responsibleContractorId?: number; /** Filter by due date before */ dueDateBefore?: Date; perPage?: number; page?: number; } export interface GetSubmittalsOptions { projectId: string; /** Filter by status ID */ statusId?: number; /** Filter by received from ID */ receivedFromId?: number; /** Filter by responsible contractor ID */ responsibleContractorId?: number; perPage?: number; page?: number; } export interface GetDailyLogsOptions { projectId: string; /** Filter by specific date */ date?: Date; /** Filter by date range start */ startDate?: Date; /** Filter by date range end */ endDate?: Date; perPage?: number; page?: number; } export interface GetChangeOrdersOptions { projectId: string; /** Filter by contract ID */ contractId?: number; /** Filter by status */ status?: string; perPage?: number; page?: number; } export interface GetBudgetOptions { projectId: string; /** Include pending costs */ includePending?: boolean; perPage?: number; page?: number; } export interface CreateRFIOptions { projectId: string; subject: string; question: string; /** Due date for response */ dueDate?: Date; /** Assignee user IDs */ assigneeIds?: number[]; /** Ball in court user ID */ ballInCourtId?: number; /** Responsible contractor ID */ responsibleContractorId?: number; /** Spec section ID */ specSectionId?: number; /** Location ID */ locationId?: number; /** Whether RFI is draft */ draft?: boolean; } export interface CreateDailyLogOptions { projectId: string; date: Date; notes?: string; weatherConditions?: { temperatureHigh?: number; temperatureLow?: number; conditions?: string; precipitation?: string; }; } export interface AddManpowerLogOptions { projectId: string; dailyLogId: number; vendorId?: number; numWorkers: number; hoursWorked?: number; notes?: string; } /** * Procore API Integration * * Weniger, aber besser: Construction project management for 2M+ users. * * API: REST v1.0/v2.0 * Auth: OAuth 2.0 (Authorization Code or Client Credentials/DMSA) * Rate Limit: 3,600 requests/hour (can request increase to 7,200 or 14,400) * Pagination: Page-based (page, per_page; max 100) */ export declare class Procore extends BaseAPIClient { private readonly companyId; constructor(config: ProcoreConfig); /** * Get default headers for Procore API requests */ private getProcoreHeaders; /** * Get company information */ getCompany(): Promise>; /** * Get all projects for the company */ getProjects(options?: GetProjectsOptions): Promise>; /** * Get a single project by ID */ getProject(projectId: string): Promise>; /** * Get RFIs for a project * * Zuhandenheit: "What RFIs need answers?" not "GET /rfis?status=open" */ getRFIs(options: GetRFIsOptions): Promise>; /** * Get open RFIs for a project (convenience method) */ getOpenRFIs(projectId: string): Promise>; /** * Get overdue RFIs */ getOverdueRFIs(projectId: string): Promise>; /** * Get a single RFI by ID */ getRFI(projectId: string, rfiId: number): Promise>; /** * Create a new RFI */ createRFI(options: CreateRFIOptions): Promise>; /** * Get submittals for a project */ getSubmittals(options: GetSubmittalsOptions): Promise>; /** * Get a single submittal by ID */ getSubmittal(projectId: string, submittalId: number): Promise>; /** * Get daily logs for a project * * Zuhandenheit: "What happened on site today?" not "GET /daily_logs?date=..." */ getDailyLogs(options: GetDailyLogsOptions): Promise>; /** * Get today's daily log */ getTodaysDailyLog(projectId: string): Promise>; /** * Create a daily log */ createDailyLog(options: CreateDailyLogOptions): Promise>; /** * Get manpower logs for a daily log */ getManpowerLogs(projectId: string, dailyLogId: number): Promise>; /** * Add manpower log entry */ addManpowerLog(options: AddManpowerLogOptions): Promise>; /** * Get change orders for a project */ getChangeOrders(options: GetChangeOrdersOptions): Promise>; /** * Get a single change order by ID */ getChangeOrder(projectId: string, changeOrderId: number): Promise>; /** * Get budget line items for a project */ getBudget(options: GetBudgetOptions): Promise>; /** * Get drawings for a project */ getDrawings(projectId: string, perPage?: number, page?: number): Promise>; /** * Get users in the company */ getUsers(perPage?: number, page?: number): Promise>; /** * Get project users */ getProjectUsers(projectId: string, perPage?: number, page?: number): Promise>; /** * Handle errors consistently */ private handleError; /** * Get capabilities for Procore actions */ private getCapabilities; } /** * Convert Procore project to standard project format */ export declare function toStandardProject(project: ProcoreProject): { id: string; name: string; displayName: string | undefined; number: string | undefined; status: string; stage: string | undefined; startDate: string | undefined; endDate: string | undefined; location: { address: string; city: string | undefined; state: string | undefined; zip: string | undefined; country: string | undefined; coordinates: { lat: number; lng: number; } | undefined; } | undefined; source: "procore"; sourceId: string; }; /** * Convert Procore RFI to standard task/issue format */ export declare function toStandardIssue(rfi: ProcoreRFI): { id: string; type: "rfi"; number: string; title: string; description: string | undefined; status: "open" | "draft" | "closed"; dueDate: string | undefined; assignee: { id: string; name: string; } | undefined; costImpact: number | undefined; scheduleImpact: number | undefined; createdAt: string; updatedAt: string; closedAt: string | undefined; source: "procore"; sourceId: string; }; /** * Convert Procore daily log to standard log format */ export declare function toStandardDailyLog(log: ProcoreDailyLog): { id: string; date: string; projectId: string; weather: { high: number | undefined; low: number | undefined; conditions: string | undefined; precipitation: string | undefined; } | undefined; notes: string | undefined; createdAt: string; updatedAt: string; source: "procore"; sourceId: string; }; //# sourceMappingURL=index.d.ts.map