{"openapi":"3.1.0","info":{"title":"RoofKit Partner API","version":"1.0.0","summary":"REST JSON API for external RoofKit partner integrations.","contact":{"name":"RoofKit Engineering"},"description":"RoofKit Partner API v1 authenticates requests with workspace API keys. API keys bind each request to exactly one workspace; Partner API paths do not accept roofer_id, workspace_id, or tenant identifiers. Authenticated endpoints are limited to 60 requests per minute per API key, method, and route template; invalid authentication attempts are limited separately at 20 requests per minute per client and endpoint.\n"},"servers":[{"url":"/","description":"Current RoofKit app origin"}],"tags":[{"name":"Foundation","description":"Authentication and contract foundation endpoints."},{"name":"Leads","description":"Partner CRM lead sync endpoints."},{"name":"Attribution","description":"Partner marketing attribution, campaign analytics, and event ingestion endpoints."},{"name":"Pipeline","description":"Partner-readable lead pipeline metadata."},{"name":"Reports","description":"Partner report import, listing, fetch, export, and download endpoints."},{"name":"Visualizer","description":"Partner Sales Visualizer creation, generation, session history, and share-link endpoints."}],"security":[{"ApiKeyBearer":[]}],"paths":{"/api/v1/me":{"get":{"tags":["Foundation"],"operationId":"Verify API key","summary":"Verify API key","description":"Returns safe metadata for the authenticated API key and bound workspace.","security":[{"ApiKeyBearer":[]}],"responses":{"200":{"description":"API key is active and bound to an active workspace.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["api_key","workspace"],"properties":{"api_key":{"$ref":"#/components/schemas/ApiKeySelf"},"workspace":{"$ref":"#/components/schemas/WorkspaceSelf"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/leads":{"get":{"tags":["Leads"],"operationId":"List leads","summary":"List leads","description":"Lists active leads for incremental CRM sync.","x-required-scopes":["leads.read"],"parameters":[{"$ref":"#/components/parameters/Source"},{"$ref":"#/components/parameters/Medium"},{"$ref":"#/components/parameters/Campaign"},{"$ref":"#/components/parameters/UpdatedFrom"},{"$ref":"#/components/parameters/UpdatedTo"},{"$ref":"#/components/parameters/StatusStageId"},{"$ref":"#/components/parameters/Search"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Active leads page.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadListResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Leads"],"operationId":"Upsert lead","summary":"Create or update lead","description":"Creates a lead or updates the matching active lead. external_id plus external_source wins when provided; otherwise normalized phone dedupe is used as fallback.\n","x-required-scopes":["leads.write"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadWrite"}}}},"responses":{"200":{"description":"Existing lead updated.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadUpsertResponse"}}}},"201":{"description":"New lead created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadUpsertResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/leads/export":{"get":{"tags":["Leads"],"operationId":"Export leads","summary":"Export leads","description":"Exports formula-safe CSV using the same filters as list leads. Exports are capped at 10,000 matching leads per response; use the returned X-Export-Next-Cursor when X-Export-Truncated is true.","x-required-scopes":["leads.export"],"parameters":[{"$ref":"#/components/parameters/Source"},{"$ref":"#/components/parameters/Medium"},{"$ref":"#/components/parameters/Campaign"},{"$ref":"#/components/parameters/UpdatedFrom"},{"$ref":"#/components/parameters/UpdatedTo"},{"$ref":"#/components/parameters/StatusStageId"},{"$ref":"#/components/parameters/Search"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"CSV export.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Content-Disposition":{"schema":{"type":"string"}},"X-Export-Truncated":{"schema":{"type":"string","enum":["true","false"]},"description":"true when additional matching rows remain after the CSV cap."},"X-Export-Next-Cursor":{"schema":{"type":"string"},"description":"Cursor to pass back to `/api/v1/leads/export` for the next export segment when truncated."}},"content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/leads/{lead_id}":{"get":{"tags":["Leads"],"operationId":"Get lead","summary":"Get lead","description":"Returns one active lead by public lead id.","x-required-scopes":["leads.read"],"parameters":[{"$ref":"#/components/parameters/LeadId"}],"responses":{"200":{"description":"Lead found.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["lead"],"properties":{"lead":{"$ref":"#/components/schemas/Lead"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Leads"],"operationId":"Patch lead","summary":"Patch lead","description":"Updates editable lead fields, pipeline stage, attribution overrides, and contact snapshots.","x-required-scopes":["leads.write"],"parameters":[{"$ref":"#/components/parameters/LeadId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadPatch"}}}},"responses":{"200":{"description":"Lead updated.","headers":{"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["lead","updated"],"properties":{"lead":{"$ref":"#/components/schemas/Lead"},"updated":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"tags":["Leads"],"operationId":"Delete lead","summary":"Delete lead","description":"Soft deletes an active lead.","x-required-scopes":["leads.write"],"parameters":[{"$ref":"#/components/parameters/LeadId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Lead soft deleted.","headers":{"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["deleted","lead_id"],"properties":{"deleted":{"type":"boolean","const":true},"lead_id":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/leads/{lead_id}/conversions":{"get":{"tags":["Leads"],"operationId":"List lead conversions","summary":"List lead conversions","description":"Returns public conversion snapshots without automation diagnostics.","x-required-scopes":["leads.read"],"parameters":[{"$ref":"#/components/parameters/LeadId"}],"responses":{"200":{"description":"Conversion snapshots.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Leads"],"operationId":"Create lead conversion","summary":"Create lead conversion","description":"Creates a public conversion snapshot. This does not dispatch automations or webhooks.","x-required-scopes":["leads.write"],"parameters":[{"$ref":"#/components/parameters/LeadId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionWrite"}}}},"responses":{"200":{"description":"Existing conversion replayed or returned by external_event_id.","headers":{"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionCreateResponse"}}}},"201":{"description":"Conversion created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionCreateResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/leads/{lead_id}/roof":{"get":{"tags":["Leads"],"operationId":"Get lead roof","summary":"Get lead roof","description":"Returns public roof detail selections and generated image URLs for the lead.","x-required-scopes":["leads.read"],"parameters":[{"$ref":"#/components/parameters/LeadId"}],"responses":{"200":{"description":"Roof detail bundle.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["roof"],"properties":{"roof":{"$ref":"#/components/schemas/LeadRoof"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports":{"get":{"tags":["Reports"],"operationId":"List reports","summary":"List reports","description":"Lists active measurement reports for incremental partner sync.","x-required-scopes":["reports.read"],"parameters":[{"$ref":"#/components/parameters/UpdatedFrom"},{"$ref":"#/components/parameters/UpdatedTo"},{"$ref":"#/components/parameters/ReportStatus"},{"$ref":"#/components/parameters/Search"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Active reports page.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportListResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports/import":{"post":{"tags":["Reports"],"operationId":"Import report","summary":"Import report","description":"Imports one standalone PDF or a legacy XML/CSV/XLSX/DXF report package. The API key supplies the workspace; tenant selector fields are rejected.\n","x-required-scopes":["reports.write"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/ContentLength"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ReportImportForm"},"examples":{"xml_report":{"summary":"Legacy XML report package","value":{"files":["@./report.xml"],"external_report_id":"vendor-123"}}}}}},"responses":{"201":{"description":"Report imported.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportImportResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"411":{"$ref":"#/components/responses/ValidationError"},"413":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports/{report_id}":{"get":{"tags":["Reports"],"operationId":"Get report","summary":"Get report","description":"Returns one active report and its export artifact metadata.","x-required-scopes":["reports.read"],"parameters":[{"$ref":"#/components/parameters/ReportId"}],"responses":{"200":{"description":"Report found.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportDetailResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports/{report_id}/export":{"post":{"tags":["Reports"],"operationId":"Export report","summary":"Export report","description":"Generates a report export from the requested revision, or from the approved/current fallback revision when revision_id is omitted. PDF exports require `reports.export_pdf`; technical formats require `reports.export_technical`.\n","x-required-scopes":["reports.write"],"x-format-required-scopes":{"pdf":"reports.export_pdf","technical":"reports.export_technical"},"parameters":[{"$ref":"#/components/parameters/ReportId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportExportRequest"}}}},"responses":{"201":{"description":"Export artifacts created.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportExportResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports/exports/{export_id}":{"get":{"tags":["Reports"],"operationId":"Get report export","summary":"Get report export","description":"Returns export artifact metadata and the public download endpoint.","x-required-scopes":["reports.read"],"parameters":[{"$ref":"#/components/parameters/ExportId"}],"responses":{"200":{"description":"Export metadata.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["export"],"properties":{"export":{"$ref":"#/components/schemas/ReportExportArtifact"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/reports/exports/{export_id}/download":{"get":{"tags":["Reports"],"operationId":"Download report export","summary":"Download report export","description":"Redirects to a short-lived signed storage URL for the export artifact.","x-required-scopes":["reports.read"],"parameters":[{"$ref":"#/components/parameters/ExportId"}],"responses":{"307":{"description":"Redirect to signed storage URL.","headers":{"Location":{"schema":{"type":"string","format":"uri"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/visualizations":{"post":{"tags":["Visualizer"],"operationId":"Create visualization","summary":"Create visualization","description":"Creates a pending Sales Visualizer row for the key-bound workspace. Partner callers cannot submit tenant selectors or completed image URLs.","x-required-scopes":["sales_visualizer.use"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationCreate"}}}},"responses":{"201":{"description":"Visualization row created.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/visualizations/{visualization_id}":{"get":{"tags":["Visualizer"],"operationId":"Get visualization","summary":"Get visualization","description":"Returns one active Sales Visualizer row by id for the key-bound workspace.","x-required-scopes":["sales_visualizer.use"],"parameters":[{"$ref":"#/components/parameters/VisualizationId"}],"responses":{"200":{"description":"Visualization found.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/visualizations/{visualization_id}/generate":{"post":{"tags":["Visualizer"],"operationId":"Generate visualization","summary":"Generate visualization","description":"Reserves one billable visualization attempt, runs the existing AI generation pipeline, stores the generated image, and completes the canonical row.","x-required-scopes":["sales_visualizer.use"],"parameters":[{"$ref":"#/components/parameters/VisualizationId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationGenerateRequest"}}}},"responses":{"200":{"description":"Visualization generated or replayed.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationGenerateResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/sessions/{session_id}/visualizations":{"get":{"tags":["Visualizer"],"operationId":"List session visualizations","summary":"List session visualizations","description":"Lists Sales Visualizer rows for a session, including pending, processing, failed, and completed states.","x-required-scopes":["sales_visualizer.use"],"parameters":[{"$ref":"#/components/parameters/SessionId"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Session visualization page.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisualizationListResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/share-links":{"post":{"tags":["Visualizer"],"operationId":"Create share link","summary":"Create share link","description":"Creates a public share link for a completed Sales Visualizer row in the key-bound workspace.","x-required-scopes":["sales_visualizer.use"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkCreateRequest"}}}},"responses":{"201":{"description":"Share link created.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkCreateResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/share-links/{token}":{"get":{"tags":["Visualizer"],"operationId":"Get share link","summary":"Get share link","description":"Public rate-limited read for a share-link token. This endpoint does not require a Partner API key.","security":[],"parameters":[{"$ref":"#/components/parameters/ShareToken"}],"responses":{"200":{"description":"Public share-link details.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkPublicResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/lead-sources":{"get":{"tags":["Attribution"],"operationId":"List lead sources","summary":"List lead sources","description":"Lists first-touch attribution source groups for the key-bound workspace.","x-required-scopes":["analytics.read"],"parameters":[{"$ref":"#/components/parameters/AttributionFrom"},{"$ref":"#/components/parameters/AttributionTo"},{"$ref":"#/components/parameters/AttributionTimezone"}],"responses":{"200":{"description":"Lead source attribution rows.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadSourcesResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/lead-sources/{source_id}":{"get":{"tags":["Attribution"],"operationId":"Get lead source","summary":"Get lead source","description":"Returns one source row and its campaign breakdown for the selected range.","x-required-scopes":["analytics.read"],"parameters":[{"$ref":"#/components/parameters/SourceId"},{"$ref":"#/components/parameters/AttributionFrom"},{"$ref":"#/components/parameters/AttributionTo"},{"$ref":"#/components/parameters/AttributionTimezone"}],"responses":{"200":{"description":"Lead source detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadSourceDetailResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/campaigns":{"get":{"tags":["Attribution"],"operationId":"List campaigns","summary":"List campaigns","description":"Lists first-touch attribution campaign groups for the key-bound workspace.","x-required-scopes":["analytics.read"],"parameters":[{"$ref":"#/components/parameters/AttributionFrom"},{"$ref":"#/components/parameters/AttributionTo"},{"$ref":"#/components/parameters/AttributionTimezone"}],"responses":{"200":{"description":"Campaign attribution rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/campaigns/{campaign}/metrics":{"get":{"tags":["Attribution"],"operationId":"Get campaign metrics","summary":"Get campaign metrics","description":"Returns one campaign row and its source breakdown for the selected range.","x-required-scopes":["analytics.read"],"parameters":[{"$ref":"#/components/parameters/CampaignId"},{"$ref":"#/components/parameters/AttributionFrom"},{"$ref":"#/components/parameters/AttributionTo"},{"$ref":"#/components/parameters/AttributionTimezone"}],"responses":{"200":{"description":"Campaign detail metrics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignMetricsResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/events/page-view":{"post":{"tags":["Attribution"],"operationId":"Track page view","summary":"Track page view","description":"Records a partner-supplied page view or landing page view event.","x-required-scopes":["analytics.manage"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageViewEventWrite"}}}},"responses":{"200":{"description":"Event duplicate or idempotent replay returned.","headers":{"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventTrackResponse"}}}},"201":{"description":"Page view event recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventTrackResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/events/form-submission":{"post":{"tags":["Attribution"],"operationId":"Track form submission","summary":"Track form submission","description":"Records a form submission event and upserts a lead when email or phone is present.","x-required-scopes":["analytics.manage"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionEventWrite"}}}},"responses":{"200":{"description":"Submission duplicate or idempotent replay returned.","headers":{"Idempotency-Replayed":{"$ref":"#/components/headers/IdempotencyReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionTrackResponse"}}}},"201":{"description":"Form submission recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionTrackResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/pipeline/stages":{"get":{"tags":["Pipeline"],"operationId":"List pipeline stages","summary":"List pipeline stages","description":"Lists active lead pipeline stages for the key-bound workspace.","x-required-scopes":["leads.read"],"responses":{"200":{"description":"Active pipeline stages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStagesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"ApiKeyBearer":{"type":"http","scheme":"bearer","bearerFormat":"RoofKit API key","description":"Use `Authorization: Bearer rk_live_...`."}},"headers":{"RateLimitLimit":{"description":"Maximum requests allowed in the current window.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests remaining in the current window.","schema":{"type":"string"}},"RateLimitReset":{"description":"ISO timestamp when the current rate-limit window resets.","schema":{"type":"string","format":"date-time"}},"RetryAfter":{"description":"Seconds until the caller should retry.","schema":{"type":"string"}},"IdempotencyReplayed":{"description":"Present and true when a stored successful write response was replayed.","schema":{"type":"string","enum":["true"]}}},"parameters":{"LeadId":{"name":"lead_id","in":"path","required":true,"schema":{"type":"string"}},"ReportId":{"name":"report_id","in":"path","required":true,"x-docs-test-value":"report_123","schema":{"type":"string","minLength":1,"maxLength":200}},"ExportId":{"name":"export_id","in":"path","required":true,"x-docs-test-value":"export_123","schema":{"type":"string","minLength":1,"maxLength":200}},"VisualizationId":{"name":"visualization_id","in":"path","required":true,"x-docs-test-value":"550e8400-e29b-41d4-a716-446655440000","schema":{"type":"string","minLength":1,"maxLength":200}},"SessionId":{"name":"session_id","in":"path","required":true,"x-docs-test-value":"session_123","schema":{"type":"string","minLength":1,"maxLength":500}},"ShareToken":{"name":"token","in":"path","required":true,"x-docs-test-value":"sharetoken123","schema":{"type":"string","minLength":10,"maxLength":128}},"SourceId":{"name":"source_id","in":"path","required":true,"description":"URL-encoded `key` returned by `/api/v1/lead-sources`.","schema":{"type":"string","minLength":1,"maxLength":500}},"CampaignId":{"name":"campaign","in":"path","required":true,"description":"URL-encoded `key` returned by `/api/v1/campaigns`.","schema":{"type":"string","minLength":1,"maxLength":500}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":160}},"ContentLength":{"name":"Content-Length","in":"header","required":true,"description":"Required for multipart report imports before request parsing. Most HTTP clients compute this automatically for multipart form uploads.","schema":{"type":"integer","minimum":1}},"Source":{"name":"source","in":"query","schema":{"type":"string","maxLength":500}},"Medium":{"name":"medium","in":"query","schema":{"type":"string","maxLength":500}},"Campaign":{"name":"campaign","in":"query","schema":{"type":"string","maxLength":500}},"UpdatedFrom":{"name":"from","in":"query","description":"Inclusive updated_at lower bound for incremental sync.","schema":{"type":"string","format":"date-time"}},"UpdatedTo":{"name":"to","in":"query","description":"Inclusive updated_at upper bound for incremental sync.","schema":{"type":"string","format":"date-time"}},"StatusStageId":{"name":"status_stage_id","in":"query","schema":{"type":"string","maxLength":150}},"ReportStatus":{"name":"status","in":"query","schema":{"type":"string","enum":["draft","needs_review","approved","failed"]}},"Search":{"name":"search","in":"query","schema":{"type":"string","maxLength":200}},"Cursor":{"name":"cursor","in":"query","description":"Opaque cursor returned by list/export responses. Send it back unchanged; malformed cursors return 400.","schema":{"type":"string","maxLength":500}},"Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"AttributionFrom":{"name":"from","in":"query","description":"Inclusive ISO datetime lower bound. Defaults to 30 days before `to` or now.","schema":{"type":"string","format":"date-time"}},"AttributionTo":{"name":"to","in":"query","description":"Exclusive ISO datetime upper bound. Defaults to the current server time.","schema":{"type":"string","format":"date-time"}},"AttributionTimezone":{"name":"timezone","in":"query","description":"IANA timezone used for analytics bounds and spend proration.","schema":{"type":"string","default":"UTC","maxLength":100}}},"responses":{"Unauthorized":{"description":"Missing, malformed, revoked, deleted, or unknown API key.","headers":{"WWW-Authenticate":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"API key lacks the required scope or the workspace is not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ValidationError":{"description":"Request payload, query, or required header is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found in the key-bound workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"Request conflicts with idempotency or external event identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"RateLimited":{"description":"Rate limit exceeded for this key and endpoint or invalid-auth bucket.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalError":{"description":"Internal authentication or server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ApiKeyScope":{"type":"string","enum":["leads.read","leads.write","leads.export","analytics.read","analytics.manage","sales_visualizer.use","reports.read","reports.write","reports.export_pdf","reports.export_technical","reports.approve","reports.assistant.use"]},"ApiKeySelf":{"type":"object","additionalProperties":false,"required":["id","name","masked_key","scopes"],"properties":{"id":{"type":"string","description":"Stable API key identifier. This is not the secret."},"name":{"type":"string"},"masked_key":{"type":"string","example":"rk_live_x8Nf4a...Q2m9"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyScope"}}}},"WorkspaceSelf":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string","description":"Bound workspace identifier."},"name":{"type":"string"}}},"ErrorCode":{"type":"string","enum":["UNAUTHORIZED","FORBIDDEN","RATE_LIMITED","VALIDATION_ERROR","NOT_FOUND","CONFLICT","INTERNAL_ERROR"]},"ErrorResponse":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","request_id"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string"},"request_id":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"CursorPagination":{"type":"object","additionalProperties":false,"required":["limit","next_cursor","has_more"],"properties":{"limit":{"type":"integer","minimum":1,"maximum":10000},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}}},"Attribution":{"type":"object","additionalProperties":false,"properties":{"source":{"type":["string","null"]},"medium":{"type":["string","null"]},"campaign":{"type":["string","null"]},"content":{"type":["string","null"]},"conversion_url":{"type":["string","null"],"format":"uri"}}},"AttributionOverrides":{"type":"object","additionalProperties":false,"properties":{"source":{"type":["string","null"]},"medium":{"type":["string","null"]},"campaign":{"type":["string","null"]},"content":{"type":["string","null"]}}},"JsonRecord":{"type":"object","additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]}}]}},"AttributionRange":{"type":"object","additionalProperties":false,"required":["from","to","timezone"],"properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"timezone":{"type":"string"}}},"AttributionMetrics":{"type":"object","additionalProperties":false,"required":["lead_count","conversion_count","conversion_rate","avg_lead_to_sold_seconds","funnel_gap_count","funnel_gap_rate","stage_counts","stages","trend","trends","automated_spend_cents","other_costs_cents","total_spend_cents","prorated_spend_cents","cpl_cents","cpa_cents","revenue_cents","roas","currency"],"properties":{"lead_count":{"type":"integer"},"conversion_count":{"type":"integer"},"conversion_rate":{"type":"number"},"avg_lead_to_sold_seconds":{"type":["number","null"]},"funnel_gap_count":{"type":"integer"},"funnel_gap_rate":{"type":"number"},"funnel_gap_stage_counts":{"type":"object","additionalProperties":{"type":"integer"}},"stage_counts":{"type":"object","additionalProperties":{"type":"integer"}},"stages":{"type":"array","items":{"type":"object","additionalProperties":true}},"trend":{"type":"object","additionalProperties":true},"trends":{"type":"object","additionalProperties":true},"automated_spend_cents":{"type":["integer","null"]},"other_costs_cents":{"type":["integer","null"]},"total_spend_cents":{"type":["integer","null"]},"prorated_spend_cents":{"type":["integer","null"]},"cpl_cents":{"type":["integer","null"]},"cpa_cents":{"type":["integer","null"]},"revenue_cents":{"type":["integer","null"]},"roas":{"type":["number","null"]},"currency":{"type":["string","null"]}}},"AttributionRow":{"type":"object","additionalProperties":false,"required":["id","key","label","source","medium","campaign","metrics"],"properties":{"id":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"source":{"type":["string","null"]},"medium":{"type":["string","null"]},"campaign":{"type":["string","null"]},"metrics":{"$ref":"#/components/schemas/AttributionMetrics"}}},"LeadSourcesResponse":{"type":"object","additionalProperties":false,"required":["lead_sources","summary","range"],"properties":{"lead_sources":{"type":"array","items":{"$ref":"#/components/schemas/AttributionRow"}},"summary":{"$ref":"#/components/schemas/AttributionMetrics"},"range":{"$ref":"#/components/schemas/AttributionRange"}}},"LeadSourceDetailResponse":{"type":"object","additionalProperties":false,"required":["lead_source","campaigns","summary","range"],"properties":{"lead_source":{"$ref":"#/components/schemas/AttributionRow"},"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/AttributionRow"}},"summary":{"$ref":"#/components/schemas/AttributionMetrics"},"range":{"$ref":"#/components/schemas/AttributionRange"}}},"CampaignsResponse":{"type":"object","additionalProperties":false,"required":["campaigns","summary","range"],"properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/AttributionRow"}},"summary":{"$ref":"#/components/schemas/AttributionMetrics"},"range":{"$ref":"#/components/schemas/AttributionRange"}}},"CampaignMetricsResponse":{"type":"object","additionalProperties":false,"required":["campaign","sources","summary","range"],"properties":{"campaign":{"$ref":"#/components/schemas/AttributionRow"},"sources":{"type":"array","items":{"$ref":"#/components/schemas/AttributionRow"}},"summary":{"$ref":"#/components/schemas/AttributionMetrics"},"range":{"$ref":"#/components/schemas/AttributionRange"}}},"PageViewEventWrite":{"type":"object","additionalProperties":false,"required":["external_event_id","session_id"],"properties":{"external_event_id":{"type":"string","minLength":1,"maxLength":200},"session_id":{"type":"string","minLength":1,"maxLength":500},"page_url":{"type":["string","null"],"format":"uri"},"referrer_url":{"type":["string","null"],"format":"uri"},"user_agent":{"type":["string","null"],"maxLength":512},"occurred_at":{"type":"string","format":"date-time"},"device_type":{"type":["string","null"],"enum":["mobile","desktop","tablet"]},"landing_id":{"type":["string","null"],"maxLength":150},"landing_name":{"type":["string","null"],"maxLength":200},"landing_slug":{"type":["string","null"],"maxLength":80}}},"FormSubmissionEventWrite":{"type":"object","additionalProperties":false,"required":["external_event_id","session_id"],"properties":{"external_event_id":{"type":"string","minLength":1,"maxLength":200},"session_id":{"type":"string","minLength":1,"maxLength":500},"page_url":{"type":["string","null"],"format":"uri"},"referrer_url":{"type":["string","null"],"format":"uri"},"user_agent":{"type":["string","null"],"maxLength":512},"occurred_at":{"type":"string","format":"date-time"},"submitted_at":{"type":"string","format":"date-time"},"form_id":{"type":["string","null"],"maxLength":200},"form_name":{"type":["string","null"],"maxLength":200},"form_selector":{"type":["string","null"],"maxLength":500},"contact_name":{"type":["string","null"],"maxLength":200},"contact_email":{"type":["string","null"],"format":"email"},"contact_phone":{"description":"US-only phone. Invalid or non-US values return VALIDATION_ERROR.","type":["string","null"]},"property_address":{"description":"Optional property address. Empty, explicit US country, or US state + ZIP formats are accepted; clearly non-US values return VALIDATION_ERROR.","type":["string","null"],"maxLength":500},"form_data":{"$ref":"#/components/schemas/JsonRecord"},"attribution_params":{"type":"object","additionalProperties":{"type":"string"}},"consent_mode":{"type":"string","enum":["implicit","required"],"default":"implicit"},"consent_granted":{"type":"boolean"}}},"EventTrackResponse":{"type":"object","additionalProperties":false,"required":["event","duplicate","created"],"properties":{"event":{"type":"object","additionalProperties":false,"required":["id"],"properties":{"id":{"type":"string"}}},"duplicate":{"type":"boolean"},"created":{"type":"boolean"}}},"FormSubmissionTrackResponse":{"type":"object","additionalProperties":false,"required":["event","duplicate","analytics_only","recorded_analytics","lead_id","created"],"properties":{"event":{"type":"object","additionalProperties":false,"required":["id"],"properties":{"id":{"type":"string"}}},"duplicate":{"type":"boolean"},"analytics_only":{"type":"boolean"},"recorded_analytics":{"type":"boolean"},"lead_id":{"type":["string","null"]},"created":{"type":"boolean"}}},"Lead":{"type":"object","additionalProperties":false,"required":["id","contact_name","contact_email","contact_phone","property_address","is_partial","status","status_stage_id","attribution","created_at","updated_at"],"properties":{"id":{"type":"string"},"external_id":{"type":["string","null"]},"external_source":{"type":["string","null"]},"contact_name":{"type":["string","null"]},"contact_email":{"type":["string","null"],"format":"email"},"contact_phone":{"description":"Stored phone digits for the lead.","type":["string","null"]},"property_address":{"description":"Property address text for the lead.","type":["string","null"]},"is_partial":{"type":"boolean"},"status":{"type":"string"},"status_stage_id":{"type":["string","null"]},"status_label":{"type":["string","null"]},"status_sort_order":{"type":["integer","null"]},"is_conversion_stage":{"type":"boolean"},"stage_timestamps":{"type":["object","null"],"additionalProperties":{"type":["string","null"]}},"funnel_gap_summary":{"type":["object","null"],"additionalProperties":true},"attribution":{"$ref":"#/components/schemas/Attribution"},"form_data":{"$ref":"#/components/schemas/JsonRecord"},"custom_fields":{"$ref":"#/components/schemas/JsonRecord"},"selected_material_id":{"type":["string","null"]},"selected_color_id":{"type":["string","null"]},"selected_shape_id":{"type":["string","null"]},"notes":{"type":["string","null"]},"estimated_value":{"type":["number","null"]},"follow_up_date":{"type":["string","null"],"format":"date-time"},"converted_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"LeadWrite":{"type":"object","additionalProperties":false,"properties":{"external_id":{"type":["string","null"],"maxLength":200},"external_source":{"type":["string","null"],"maxLength":120},"is_partial":{"type":"boolean"},"session_id":{"type":["string","null"],"maxLength":500},"contact_name":{"type":["string","null"],"maxLength":200},"contact_email":{"type":["string","null"],"format":"email"},"contact_phone":{"description":"US-only phone. Invalid or non-US values return VALIDATION_ERROR.","type":["string","null"]},"property_address":{"description":"Optional property address. Empty, explicit US country, or US state + ZIP formats are accepted; clearly non-US values return VALIDATION_ERROR.","type":["string","null"],"maxLength":500},"form_data":{"$ref":"#/components/schemas/JsonRecord"},"custom_fields":{"$ref":"#/components/schemas/JsonRecord"},"selected_material_id":{"type":["string","null"]},"selected_color_id":{"type":["string","null"]},"selected_shape_id":{"type":["string","null"]},"status_stage_id":{"type":"string"},"attribution":{"$ref":"#/components/schemas/Attribution"},"marketing_attribution_overrides":{"$ref":"#/components/schemas/AttributionOverrides"},"notes":{"type":["string","null"],"maxLength":5000},"estimated_value":{"type":["number","null"],"minimum":0,"maximum":10000000},"follow_up_date":{"type":["string","null"],"format":"date-time"}}},"LeadPatch":{"type":"object","additionalProperties":false,"properties":{"is_partial":{"type":"boolean"},"contact_name":{"type":["string","null"],"maxLength":200},"contact_email":{"type":["string","null"],"format":"email"},"contact_phone":{"description":"US-only phone. Invalid or non-US values return VALIDATION_ERROR.","type":["string","null"]},"property_address":{"description":"Optional property address. Empty, explicit US country, or US state + ZIP formats are accepted; clearly non-US values return VALIDATION_ERROR.","type":["string","null"],"maxLength":500},"form_data":{"$ref":"#/components/schemas/JsonRecord"},"custom_fields":{"$ref":"#/components/schemas/JsonRecord"},"selected_material_id":{"type":["string","null"]},"selected_color_id":{"type":["string","null"]},"selected_shape_id":{"type":["string","null"]},"status_stage_id":{"type":"string"},"attribution":{"$ref":"#/components/schemas/Attribution"},"marketing_attribution_overrides":{"$ref":"#/components/schemas/AttributionOverrides"},"notes":{"type":["string","null"],"maxLength":5000},"estimated_value":{"type":["number","null"],"minimum":0,"maximum":10000000},"follow_up_date":{"type":["string","null"],"format":"date-time"}}},"LeadListResponse":{"type":"object","additionalProperties":false,"required":["leads","pagination"],"properties":{"leads":{"type":"array","items":{"$ref":"#/components/schemas/Lead"}},"pagination":{"$ref":"#/components/schemas/CursorPagination"}}},"LeadUpsertResponse":{"type":"object","additionalProperties":false,"required":["lead","created"],"properties":{"lead":{"$ref":"#/components/schemas/Lead"},"created":{"type":"boolean"}}},"ConversionWrite":{"type":"object","additionalProperties":false,"required":["external_event_id"],"properties":{"external_event_id":{"type":"string","minLength":1,"maxLength":200},"session_id":{"type":["string","null"]},"visualization_id":{"type":["string","null"]},"conversion_url":{"type":["string","null"],"format":"uri"},"contact_name":{"type":["string","null"]},"contact_email":{"type":["string","null"],"format":"email"},"contact_phone":{"description":"US-only phone. Invalid or non-US values return VALIDATION_ERROR.","type":["string","null"]},"property_address":{"description":"Optional property address. Empty, explicit US country, or US state + ZIP formats are accepted; clearly non-US values return VALIDATION_ERROR.","type":["string","null"]},"occurred_at":{"type":"string","format":"date-time"}}},"Conversion":{"type":"object","additionalProperties":false,"required":["id","lead_id","external_event_id","conversion_number","session_id","attribution","created_at"],"properties":{"id":{"type":"string"},"lead_id":{"type":"string"},"external_event_id":{"type":["string","null"]},"conversion_number":{"type":"integer"},"session_id":{"type":"string"},"visualization_id":{"type":["string","null"]},"attribution":{"$ref":"#/components/schemas/Attribution"},"contact_name":{"type":["string","null"]},"contact_email":{"type":["string","null"]},"contact_phone":{"description":"Phone snapshot at conversion time.","type":["string","null"]},"property_address":{"description":"Property address snapshot at conversion time.","type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}},"ConversionListResponse":{"type":"object","additionalProperties":false,"required":["conversions"],"properties":{"conversions":{"type":"array","items":{"$ref":"#/components/schemas/Conversion"}}}},"ConversionCreateResponse":{"type":"object","additionalProperties":false,"required":["conversion","created"],"properties":{"conversion":{"$ref":"#/components/schemas/Conversion"},"created":{"type":"boolean"}}},"LeadRoof":{"type":"object","additionalProperties":false,"required":["lead_id","visualization_id","material","color","shape","images"],"properties":{"lead_id":{"type":"string"},"visualization_id":{"type":["string","null"]},"material":{"type":["object","null"],"additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"color":{"type":["object","null"],"additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"hex_code":{"type":["string","null"]}}},"shape":{"type":["object","null"],"additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"roof_type":{"type":["string","null"]}}},"images":{"type":"object","additionalProperties":false,"required":["original_image_url","generated_image_url"],"properties":{"original_image_url":{"type":["string","null"]},"generated_image_url":{"type":["string","null"]}}},"processing_status":{"type":["string","null"]},"processing_error":{"type":["string","null"]}}},"ReportArtifactFormat":{"type":"string","enum":["xml","csv","xlsx","dxf","pdf","json","zip","manifest","tif","png","jpg","jpeg","webp","gif"]},"ReportStatus":{"type":"string","enum":["importing","needs_review","draft","ready_for_review","approved","exporting","failed","archived"]},"Report":{"type":"object","additionalProperties":false,"required":["id","project_name","external_report_id","status","current_revision_id","baseline_revision_id","approved_revision_id","source_formats","summary","current_revision_number","project_address","location_label","location_lat","location_long","created_at","updated_at"],"properties":{"id":{"type":"string"},"project_name":{"type":"string"},"external_report_id":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/ReportStatus"},"current_revision_id":{"type":["string","null"]},"baseline_revision_id":{"type":["string","null"]},"approved_revision_id":{"type":["string","null"]},"source_formats":{"type":"array","items":{"$ref":"#/components/schemas/ReportArtifactFormat"}},"summary":{"type":"object","additionalProperties":true},"current_revision_number":{"type":["integer","null"]},"project_address":{"type":["string","null"]},"location_label":{"type":["string","null"]},"location_lat":{"type":["number","null"]},"location_long":{"type":["number","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ReportExportArtifact":{"type":"object","additionalProperties":false,"required":["export_id","report_id","revision_id","format","file_name","mime_type","size_bytes","checksum"],"properties":{"export_id":{"type":"string"},"report_id":{"type":"string"},"revision_id":{"type":["string","null"]},"format":{"$ref":"#/components/schemas/ReportArtifactFormat"},"role":{"type":"string","enum":["export","manifest"]},"file_name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":0},"checksum":{"type":"string"},"metadata":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"download_url":{"type":"string","format":"uri"}}},"ReportListResponse":{"type":"object","additionalProperties":false,"required":["reports","pagination"],"properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/Report"}},"pagination":{"$ref":"#/components/schemas/CursorPagination"}}},"ReportDetailResponse":{"type":"object","additionalProperties":false,"required":["report","exports"],"properties":{"report":{"$ref":"#/components/schemas/Report"},"exports":{"type":"array","items":{"$ref":"#/components/schemas/ReportExportArtifact"}}}},"ReportImportForm":{"type":"object","additionalProperties":false,"required":["files"],"properties":{"files":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"string","format":"binary"}},"project_name":{"type":"string","maxLength":200},"external_report_id":{"type":"string","maxLength":200},"profile_key":{"type":"string","maxLength":120},"coverage_in":{"type":"number","exclusiveMinimum":0},"stock_width_in":{"type":"number","exclusiveMinimum":0}}},"ReportImportResponse":{"type":"object","additionalProperties":false,"required":["report_id","baseline_revision_id","working_revision_id","assistant_thread_id"],"properties":{"report_id":{"type":"string"},"baseline_revision_id":{"type":"string"},"working_revision_id":{"type":"string"},"assistant_thread_id":{"type":"string"}}},"ReportExportRequest":{"type":"object","additionalProperties":false,"required":["format"],"properties":{"revision_id":{"type":"string","maxLength":200},"format":{"type":"string","enum":["pdf","dxf","csv","xlsx","xml","zip"]}}},"ReportExportResponse":{"type":"object","additionalProperties":false,"required":["revision_id","exports"],"properties":{"revision_id":{"type":"string"},"exports":{"type":"array","items":{"$ref":"#/components/schemas/ReportExportArtifact"}}}},"VisualizationProcessingStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"Visualization":{"type":"object","additionalProperties":false,"required":["id","session_id","source","landing_id","landing_name","landing_slug","selected_material_id","selected_color_id","selected_shape_id","original_image_url","processed_image_url","processing_status","processing_started_at","processing_completed_at","processing_error","created_at","updated_at"],"properties":{"id":{"type":"string"},"session_id":{"type":"string"},"source":{"type":"string","const":"sales_visualizer"},"landing_id":{"type":["string","null"]},"landing_name":{"type":["string","null"]},"landing_slug":{"type":["string","null"]},"selected_material_id":{"type":["string","null"]},"selected_color_id":{"type":["string","null"]},"selected_shape_id":{"type":["string","null"]},"original_image_url":{"type":"string"},"processed_image_url":{"type":["string","null"]},"processing_status":{"$ref":"#/components/schemas/VisualizationProcessingStatus"},"processing_started_at":{"type":["string","null"],"format":"date-time"},"processing_completed_at":{"type":["string","null"],"format":"date-time"},"processing_error":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"VisualizationCreate":{"type":"object","additionalProperties":false,"required":["session_id","original_image_url"],"properties":{"session_id":{"type":"string","maxLength":500,"example":"session_123"},"landing_id":{"type":["string","null"],"maxLength":150},"landing_name":{"type":["string","null"],"maxLength":200},"landing_slug":{"type":["string","null"],"maxLength":80},"selected_material_id":{"type":["string","null"],"maxLength":150},"selected_color_id":{"type":["string","null"],"maxLength":150},"selected_shape_id":{"type":["string","null"],"maxLength":150},"original_image_url":{"type":"string","example":"https://example.com/house.jpg"}}},"VisualizationResponse":{"type":"object","additionalProperties":false,"required":["visualization"],"properties":{"visualization":{"$ref":"#/components/schemas/Visualization"}}},"VisualizationGenerateRequest":{"type":"object","additionalProperties":false,"required":["photo_url","material_name","color_name"],"properties":{"photo_url":{"type":"string","example":"https://example.com/house.jpg"},"material_name":{"type":"string","maxLength":100,"example":"Architectural Shingle"},"color_name":{"type":"string","maxLength":100,"example":"Charcoal"},"color_hex":{"type":"string","maxLength":7,"example":"#333333"},"shape_name":{"type":"string","maxLength":100},"reference_roof_image_url":{"type":"string","maxLength":2000000,"description":"Optional reference image as a secure HTTPS URL or data:image URL."}}},"VisualizationGenerateResponse":{"type":"object","additionalProperties":false,"required":["generation","visualization"],"properties":{"generation":{"type":"object","additionalProperties":false,"required":["visualization_url"],"properties":{"visualization_url":{"type":"string"}}},"visualization":{"$ref":"#/components/schemas/Visualization"}}},"VisualizationListResponse":{"type":"object","additionalProperties":false,"required":["visualizations","pagination"],"properties":{"visualizations":{"type":"array","items":{"$ref":"#/components/schemas/Visualization"}},"pagination":{"$ref":"#/components/schemas/CursorPagination"}}},"ShareLinkCreateRequest":{"type":"object","additionalProperties":false,"required":["visualization_id"],"properties":{"visualization_id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}},"ShareLink":{"type":"object","additionalProperties":false,"required":["token","visualization_id","created_at","url"],"properties":{"token":{"type":"string"},"visualization_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"url":{"type":"string"}}},"ShareLinkCreateResponse":{"type":"object","additionalProperties":false,"required":["share_link"],"properties":{"share_link":{"$ref":"#/components/schemas/ShareLink"}}},"ShareLinkPublicResponse":{"type":"object","additionalProperties":false,"required":["share_link","visualization","selections","roofer","landing","settings"],"properties":{"share_link":{"type":"object","additionalProperties":true},"visualization":{"type":"object","additionalProperties":true},"selections":{"type":"object","additionalProperties":true},"roofer":{"type":"object","additionalProperties":true},"landing":{"type":["object","null"],"additionalProperties":true},"settings":{"type":["object","null"],"additionalProperties":true}}},"PipelineStage":{"type":"object","additionalProperties":false,"required":["id","label","sort_order","system_key","is_conversion_stage"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"sort_order":{"type":"integer"},"system_key":{"type":["string","null"]},"is_conversion_stage":{"type":"boolean"}}},"PipelineStagesResponse":{"type":"object","additionalProperties":false,"required":["stages"],"properties":{"stages":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStage"}}}}}}}