Estimates

Update an existing estimate

Submits an update request for an existing estimate job. Creates a new version with the provided prompt instructions.

Requirements:

  • The initial estimate (version 1) must be completed before updates are accepted
  • If a previous update is still in progress, it will be canceled and superseded by this request

File Handling:

  • New file IDs are additive — they are added to the job's existing files
  • Files added in this update are tracked on the new version

Base Estimate Items:

  • If items array is provided, it will be used as the base for the update
  • If not provided, the most recent completed version's items will be used

Optional Job Updates:

  • callbackUrl and metadata can be updated on the job (other job fields are immutable)
post/v1/estimate/{estimateJobId}/update

Request

  • Base URL: https://api.handoff.ai
  • URL: https://api.handoff.ai/v1/estimate/{estimateJobId}/update
  • Auth: HTTP bearer

Path parameters

estimateJobIdstring required

The estimate job ID or external ID

Example:e1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c

Request body

promptstring required

Instructions for what to change in the estimate

fileIdsstring[]

Additional file IDs to attach to the estimate job. These are additive — they do not replace existing files.

callbackUrlstring uri

Webhook URL for job completion notification. If provided, updates the job's callback URL.

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

{
  "prompt": "Add 20 bags of concrete mix and remove the drywall items",
  "fileIds": [
    "f1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c"
  ],
  "items": [
    {
      "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "group": "Framing",
      "productName": "2x6 PT Bottom Plates",
      "quantity": 3100,
      "description": "Pressure treated bottom plates",
      "category": "material",
      "unitAbbreviation": "LF",
      "currency": "USD",
      "productId": "4564606"
    }
  ],
  "callbackUrl": "https://partners.example.com/webhooks/estimate",
  "metadata": {
    "includeMEP": true,
    "source": "takeoff-api",
    "projectId": "proj-123"
  }
}

Response

Update version 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

versionNumbernumber required

Version number of the new estimate version

createdAtstring date-time required

ISO 8601 timestamp of version creation

estimatedCompletionTimestring date-time required

ISO 8601 timestamp of expected completion

streamUrlstring required

Server-Sent Events (SSE) URL for live AI-agent + matching progress while this update processes. Optional to consume; the authoritative result still arrives via webhook and GET. Reconnect with the Last-Event-ID header to resume.

metadataobject

Custom metadata provided during job creation or update

Example response

{
  "estimateJobId": "e1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c",
  "status": "PENDING",
  "versionNumber": 2,
  "createdAt": "2025-12-05T14:30:00Z",
  "estimatedCompletionTime": "2025-12-05T14:31:00Z",
  "streamUrl": "https://api.example.com/v1/estimate/e1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c/stream",
  "metadata": {
    "includeMEP": true,
    "source": "takeoff-api",
    "projectId": "proj-123"
  }
}

Changes

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