curl --request POST \
--url https://api.roofkit.ai/api/v1/budget-estimates \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"address": "100 Congress Ave, Austin, TX 78701",
"place_id": "<string>",
"lat": 0,
"lng": 0,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
'import requests
url = "https://api.roofkit.ai/api/v1/budget-estimates"
payload = {
"address": "100 Congress Ave, Austin, TX 78701",
"place_id": "<string>",
"lat": 0,
"lng": 0,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: '100 Congress Ave, Austin, TX 78701',
place_id: '<string>',
lat: 0,
lng: 0,
selected_material_id: '<string>',
selected_shape_id: '<string>',
selected_color_id: '<string>'
})
};
fetch('https://api.roofkit.ai/api/v1/budget-estimates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roofkit.ai/api/v1/budget-estimates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'address' => '100 Congress Ave, Austin, TX 78701',
'place_id' => '<string>',
'lat' => 0,
'lng' => 0,
'selected_material_id' => '<string>',
'selected_shape_id' => '<string>',
'selected_color_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roofkit.ai/api/v1/budget-estimates"
payload := strings.NewReader("{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roofkit.ai/api/v1/budget-estimates")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roofkit.ai/api/v1/budget-estimates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"budget_estimate": {
"status": "ready",
"area_sqft": 123,
"roofing_squares": 123,
"min_price": 123,
"max_price": 123,
"exact_price": 123,
"price_display_mode": "exact",
"currency": "USD",
"complexity_tier": "simple",
"confidence": "low",
"provider": "<string>",
"map_lat": 123,
"map_lng": 123,
"disclaimer": "<string>",
"estimate_id": "<string>",
"price_range_percentage": 123,
"price_range_type": "<string>",
"map_zoom": 123,
"base_price_cents_per_sqft": 123,
"modifier_cents_per_sqft": 123,
"price_cents_per_sqft": 123,
"data_layer_preview_available": true,
"solar_estimate": {},
"options": [
{
"material_key": "<string>",
"material_id": "<string>",
"exact_price": 123,
"min_price": 123,
"max_price": 123
}
],
"preferred_material_id": "<string>",
"preferred_color_id": "<string>",
"preferred_manufacturer": "<string>"
},
"input": {
"address": "<string>",
"place_id": "<string>",
"lat": 123,
"lng": 123,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "FORBIDDEN",
"message": "API key does not include the required scope: leads.write.",
"request_id": "req_123",
"details": {
"required_scope": "leads.write",
"missing_scopes": [
"leads.write"
]
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}Create budget estimate
Runs the RoofKit Budget Estimate for a property address with the pricing of the key-bound workspace. RoofKit measures the roof from satellite data and charges the workspace once per estimate. The call is synchronous and can take up to two minutes. A fallback status has no usable roof area and must be shown as “review required”, not as a price. The response never contains the per-material installed rate.
curl --request POST \
--url https://api.roofkit.ai/api/v1/budget-estimates \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"address": "100 Congress Ave, Austin, TX 78701",
"place_id": "<string>",
"lat": 0,
"lng": 0,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
'import requests
url = "https://api.roofkit.ai/api/v1/budget-estimates"
payload = {
"address": "100 Congress Ave, Austin, TX 78701",
"place_id": "<string>",
"lat": 0,
"lng": 0,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: '100 Congress Ave, Austin, TX 78701',
place_id: '<string>',
lat: 0,
lng: 0,
selected_material_id: '<string>',
selected_shape_id: '<string>',
selected_color_id: '<string>'
})
};
fetch('https://api.roofkit.ai/api/v1/budget-estimates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roofkit.ai/api/v1/budget-estimates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'address' => '100 Congress Ave, Austin, TX 78701',
'place_id' => '<string>',
'lat' => 0,
'lng' => 0,
'selected_material_id' => '<string>',
'selected_shape_id' => '<string>',
'selected_color_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roofkit.ai/api/v1/budget-estimates"
payload := strings.NewReader("{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roofkit.ai/api/v1/budget-estimates")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roofkit.ai/api/v1/budget-estimates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"address\": \"100 Congress Ave, Austin, TX 78701\",\n \"place_id\": \"<string>\",\n \"lat\": 0,\n \"lng\": 0,\n \"selected_material_id\": \"<string>\",\n \"selected_shape_id\": \"<string>\",\n \"selected_color_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"budget_estimate": {
"status": "ready",
"area_sqft": 123,
"roofing_squares": 123,
"min_price": 123,
"max_price": 123,
"exact_price": 123,
"price_display_mode": "exact",
"currency": "USD",
"complexity_tier": "simple",
"confidence": "low",
"provider": "<string>",
"map_lat": 123,
"map_lng": 123,
"disclaimer": "<string>",
"estimate_id": "<string>",
"price_range_percentage": 123,
"price_range_type": "<string>",
"map_zoom": 123,
"base_price_cents_per_sqft": 123,
"modifier_cents_per_sqft": 123,
"price_cents_per_sqft": 123,
"data_layer_preview_available": true,
"solar_estimate": {},
"options": [
{
"material_key": "<string>",
"material_id": "<string>",
"exact_price": 123,
"min_price": 123,
"max_price": 123
}
],
"preferred_material_id": "<string>",
"preferred_color_id": "<string>",
"preferred_manufacturer": "<string>"
},
"input": {
"address": "<string>",
"place_id": "<string>",
"lat": 123,
"lng": 123,
"selected_material_id": "<string>",
"selected_shape_id": "<string>",
"selected_color_id": "<string>"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "FORBIDDEN",
"message": "API key does not include the required scope: leads.write.",
"request_id": "req_123",
"details": {
"required_scope": "leads.write",
"missing_scopes": [
"leads.write"
]
}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"request_id": "<string>",
"details": {}
}
}sales_visualizer.useAuthorizations
Use Authorization: Bearer rk_live_....
Headers
A unique value for each new request, such as a UUID. Send the same value to retry a request safely. The same key and payload replay the first response with Idempotency-Replayed: true.
1 - 160Body
3 - 500"100 Congress Ave, Austin, TX 78701"
Google Places id. RoofKit uses it to locate the property when lat and lng are absent.
500Send with lng. Without both, RoofKit geocodes the address.
-90 <= x <= 90-180 <= x <= 180150150150