Estimates

Create estimate from files

Creates an estimate from uploaded files. The type parameter determines whether to process as a MATERIAL_LIST or BLUEPRINT. Processing occurs asynchronously with results delivered via webhook.

Type-Specific Requirements:

  • BLUEPRINT: Requires fileIds to be provided (blueprint files must be uploaded)
  • MATERIAL_LIST: Requires either fileIds or prompt (or both)

Workflow:

  1. Upload files using POST /v1/files/upload-urls
  2. Submit file IDs to this endpoint for estimate creation
  3. Receive results via webhook or poll using GET /v1/estimate/{estimateJobId}

Response Delivery:

  • Results are delivered via webhook to the provided callbackUrl
  • Alternatively, poll the job status using GET /v1/estimate/{estimateJobId}
post/v1/estimate

Request

  • Base URL: https://api.handoff.ai
  • URL: https://api.handoff.ai/v1/estimate
  • Auth: HTTP bearer

Request body

type'MATERIAL_LIST' | 'BLUEPRINT' required

Type of estimate request: 'MATERIAL_LIST' for material lists or 'BLUEPRINT' for blueprints

fileIdsstring[]

List of file IDs to generate an estimate from. Required when type is 'BLUEPRINT'. Optional when type is 'MATERIAL_LIST' (can use 'prompt' instead or both)

addressstring

Address or ZIP code for regional availability and pricing

promptstring

Special instructions and scope of work for the estimate (e.g., 'Create an estimate for framing and painting.')

callbackUrlstring uri

Webhook URL for job completion notification

externalIdstring

Partner's internal estimate ID (e.g., associate-facing ID)

storeReferencestring

Store, location, or region identifier for applying store-level AI presets

customerReferencestring

Partner's internal reference/order number for tracking specific customers and applying customer-level AI presets

takeoffProduct'WINDOWS_DOORS'

Purchased takeoff product. Controls product-specific presets and commercial behavior. Omit when directly restricting trades without purchasing a named product. Only valid when type is 'BLUEPRINT'

takeoffTradesstring[]

Allowlist of trades that may appear in the takeoff. When combined with takeoffProduct, it may only narrow that product's included trades. Omit for the product's full scope or an unrestricted takeoff. Only valid when type is 'BLUEPRINT'

metadataobject

Custom key-value pairs for tracking context. Keys must be alphanumeric with underscores, max 64 chars. Values can be strings (max 256 chars), numbers, or arrays. Maximum 20 pairs.

Example request

{
  "type": "MATERIAL_LIST",
  "fileIds": [
    "f1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c",
    "f2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d"
  ],
  "address": "Austin, TX 78701",
  "prompt": "Create an estimate for framing and painting.",
  "callbackUrl": "https://partners.example.com/webhooks/estimate",
  "externalId": "EST-12345",
  "storeReference": "STORE-NYC-001",
  "customerReference": "CUST-ORD-789",
  "takeoffProduct": "WINDOWS_DOORS",
  "takeoffTrades": [
    "WINDOWS",
    "DOORS"
  ],
  "metadata": {
    "includeMEP": true,
    "source": "takeoff-api",
    "projectId": "proj-123"
  }
}

Response

Estimate job created successfully

estimateJobIdstring uuid required

Unique identifier for the estimate job

status'PENDING' | 'EXTRACTING' | 'LABELING' | 'AGENTIC_TAKEOFF' | 'INGESTING' | 'PROCESSING' | 'HUMAN_REVIEW' | 'COMPLETED' | 'FAILED' | 'CANCELED' required

Current job status. Possible values: PENDING, EXTRACTING, LABELING, AGENTIC_TAKEOFF, INGESTING, PROCESSING, HUMAN_REVIEW, COMPLETED, FAILED, CANCELED

createdAtstring date-time required

ISO 8601 timestamp of job creation

estimatedCompletionTimestring date-time required

ISO 8601 timestamp of expected completion

metadataobject

Custom metadata provided during job creation

Example response

{
  "estimateJobId": "e1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c",
  "status": "PROCESSING",
  "createdAt": "2025-12-05T14:30:00Z",
  "estimatedCompletionTime": "2025-12-05T14:31:00Z",
  "metadata": {
    "includeMEP": true,
    "source": "takeoff-api",
    "projectId": "proj-123"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.