Quick Start Examples
JavaScript
Python
PHP
cURL
JavaScript/Node.js Integration
Installation
npm install axios
# or
npm install @serviceflow-pro/visualizer-sdk
Basic Setup
const axios = require('axios');
class VisualizerAPI {
constructor(apiKey, userId, businessId) {
this.client = axios.create({
baseURL: 'https://visualizer-api.serviceflow-pro.com/api/v1',
headers: {
'X-API-Key': apiKey,
'X-User-ID': userId,
'X-Business-ID': businessId,
'Content-Type': 'application/json'
}
});
}
// Create a new visualization session
async createSession(fileId, sessionType = 'adu_pool') {
try {
const response = await this.client.post('/visualizer/sessions', {
fileId: fileId,
sessionType: sessionType,
description: 'Property visualization analysis'
});
return response.data;
} catch (error) {
console.error('Error creating session:', error.response?.data);
throw error;
}
}
// Get available ADU types
async getADUTypes() {
try {
const response = await this.client.get('/catalog/adu-types');
return response.data;
} catch (error) {
console.error('Error fetching ADU types:', error.response?.data);
throw error;
}
}
// Create a design
async createDesign(sessionId, designConfig) {
try {
const response = await this.client.post('/designs', {
sessionId: sessionId,
designType: designConfig.type,
configuration: designConfig
});
return response.data;
} catch (error) {
console.error('Error creating design:', error.response?.data);
throw error;
}
}
// Calculate pricing
async calculatePricing(designId, location) {
try {
const response = await this.client.post('/pricing/calculate', {
designId: designId,
location: location
});
return response.data;
} catch (error) {
console.error('Error calculating pricing:', error.response?.data);
throw error;
}
}
// Generate quote
async generateQuote(designId, customerInfo) {
try {
const response = await this.client.post('/quotes/generate', {
designId: designId,
customerInfo: customerInfo
});
return response.data;
} catch (error) {
console.error('Error generating quote:', error.response?.data);
throw error;
}
}
}
// Usage example
async function main() {
const api = new VisualizerAPI('your-api-key', 'your-user-id', 'your-business-id');
try {
// Create session
const session = await api.createSession('photo-file-id');
console.log('Session created:', session.id);
// Get ADU types
const aduTypes = await api.getADUTypes();
console.log('Available ADU types:', aduTypes);
// Create design
const design = await api.createDesign(session.id, {
type: 'adu',
size: '600_sqft',
materials: {
exterior: 'fiber_cement',
roofing: 'asphalt_shingle'
}
});
console.log('Design created:', design.id);
// Calculate pricing
const pricing = await api.calculatePricing(design.id, {
zipCode: '90210',
state: 'CA'
});
console.log('Pricing:', pricing);
} catch (error) {
console.error('API Error:', error.message);
}
}
main();
Express.js Integration
const express = require('express');
const multer = require('multer');
const VisualizerAPI = require('./visualizer-api');
const app = express();
const upload = multer({ dest: 'uploads/' });
const visualizerAPI = new VisualizerAPI(
process.env.VISUALIZER_API_KEY,
process.env.USER_ID,
process.env.BUSINESS_ID
);
app.use(express.json());
// Upload photo and create session
app.post('/api/visualize', upload.single('photo'), async (req, res) => {
try {
// In a real implementation, you'd upload the file to your storage
const fileId = 'uploaded-file-id';
const session = await visualizerAPI.createSession(fileId);
res.json({ success: true, sessionId: session.id });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Get design options
app.get('/api/catalog/:type', async (req, res) => {
try {
const { type } = req.params;
let catalog;
if (type === 'adu') {
catalog = await visualizerAPI.getADUTypes();
} else if (type === 'pool') {
catalog = await visualizerAPI.getPoolTypes();
}
res.json(catalog);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Create design and get pricing
app.post('/api/design', async (req, res) => {
try {
const { sessionId, designConfig, location } = req.body;
const design = await visualizerAPI.createDesign(sessionId, designConfig);
const pricing = await visualizerAPI.calculatePricing(design.id, location);
res.json({
design: design,
pricing: pricing
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Python Integration
Installation
pip install requests
# or
pip install serviceflow-visualizer-sdk
Basic Setup
import requests
import json
from typing import Dict, List, Optional
class VisualizerAPI:
def __init__(self, api_key: str, user_id: str, business_id: str):
self.base_url = 'https://visualizer-api.serviceflow-pro.com/api/v1'
self.headers = {
'X-API-Key': api_key,
'X-User-ID': user_id,
'X-Business-ID': business_id,
'Content-Type': 'application/json'
}
def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None) -> Dict:
"""Make HTTP request to the API"""
url = f'{self.base_url}{endpoint}'
try:
if method.upper() == 'GET':
response = requests.get(url, headers=self.headers)
elif method.upper() == 'POST':
response = requests.post(url, headers=self.headers, json=data)
elif method.upper() == 'PATCH':
response = requests.patch(url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f'API Error: {e}')
raise
def create_session(self, file_id: str, session_type: str = 'adu_pool') -> Dict:
"""Create a new visualization session"""
data = {
'fileId': file_id,
'sessionType': session_type,
'description': 'Property visualization analysis'
}
return self._make_request('POST', '/visualizer/sessions', data)
def get_sessions(self) -> List[Dict]:
"""Get all sessions for the business"""
return self._make_request('GET', '/visualizer/sessions')
def get_session(self, session_id: str) -> Dict:
"""Get specific session details"""
return self._make_request('GET', f'/visualizer/sessions/{session_id}')
def get_adu_types(self) -> List[Dict]:
"""Get available ADU types"""
return self._make_request('GET', '/catalog/adu-types')
def get_pool_types(self) -> List[Dict]:
"""Get available pool types"""
return self._make_request('GET', '/catalog/pool-types')
def create_design(self, session_id: str, design_config: Dict) -> Dict:
"""Create a new design"""
data = {
'sessionId': session_id,
'designType': design_config.get('type'),
'configuration': design_config
}
return self._make_request('POST', '/designs', data)
def calculate_pricing(self, design_id: str, location: Dict) -> Dict:
"""Calculate pricing for a design"""
data = {
'designId': design_id,
'location': location
}
return self._make_request('POST', '/pricing/calculate', data)
def generate_quote(self, design_id: str, customer_info: Dict) -> Dict:
"""Generate a quote"""
data = {
'designId': design_id,
'customerInfo': customer_info
}
return self._make_request('POST', '/quotes/generate', data)
# Usage example
def main():
api = VisualizerAPI('your-api-key', 'your-user-id', 'your-business-id')
try:
# Create session
session = api.create_session('photo-file-id')
print(f'Session created: {session["id"]}')
# Get ADU types
adu_types = api.get_adu_types()
print(f'Available ADU types: {len(adu_types)}')
# Create design
design_config = {
'type': 'adu',
'size': '600_sqft',
'materials': {
'exterior': 'fiber_cement',
'roofing': 'asphalt_shingle'
},
'features': ['deck', 'storage']
}
design = api.create_design(session['id'], design_config)
print(f'Design created: {design["id"]}')
# Calculate pricing
location = {
'zipCode': '90210',
'state': 'CA'
}
pricing = api.calculate_pricing(design['id'], location)
print(f'Total cost: ${pricing["totalCost"]:,.2f}')
except Exception as e:
print(f'Error: {e}')
if __name__ == '__main__':
main()
Django Integration
# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import json
from .visualizer_api import VisualizerAPI
# Initialize API client
visualizer_api = VisualizerAPI(
settings.VISUALIZER_API_KEY,
settings.USER_ID,
settings.BUSINESS_ID
)
@csrf_exempt
@require_http_methods(["POST"])
def create_visualization_session(request):
try:
data = json.loads(request.body)
file_id = data.get('fileId')
session = visualizer_api.create_session(file_id)
return JsonResponse({'success': True, 'sessionId': session['id']})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
@require_http_methods(["GET"])
def get_catalog(request, catalog_type):
try:
if catalog_type == 'adu':
catalog = visualizer_api.get_adu_types()
elif catalog_type == 'pool':
catalog = visualizer_api.get_pool_types()
else:
return JsonResponse({'error': 'Invalid catalog type'}, status=400)
return JsonResponse({'catalog': catalog})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
@csrf_exempt
@require_http_methods(["POST"])
def create_design_with_pricing(request):
try:
data = json.loads(request.body)
session_id = data.get('sessionId')
design_config = data.get('designConfig')
location = data.get('location')
# Create design
design = visualizer_api.create_design(session_id, design_config)
# Calculate pricing
pricing = visualizer_api.calculate_pricing(design['id'], location)
return JsonResponse({
'design': design,
'pricing': pricing
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
PHP Integration
Basic Setup
baseUrl = 'https://visualizer-api.serviceflow-pro.com/api/v1';
$this->headers = [
'X-API-Key: ' . $apiKey,
'X-User-ID: ' . $userId,
'X-Business-ID: ' . $businessId,
'Content-Type: application/json'
];
}
private function makeRequest($method, $endpoint, $data = null) {
$url = $this->baseUrl . $endpoint;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
} elseif ($method === 'PATCH') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
if ($data) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new Exception('API Error: HTTP ' . $httpCode . ' - ' . $response);
}
return json_decode($response, true);
}
public function createSession($fileId, $sessionType = 'adu_pool') {
$data = [
'fileId' => $fileId,
'sessionType' => $sessionType,
'description' => 'Property visualization analysis'
];
return $this->makeRequest('POST', '/visualizer/sessions', $data);
}
public function getSessions() {
return $this->makeRequest('GET', '/visualizer/sessions');
}
public function getADUTypes() {
return $this->makeRequest('GET', '/catalog/adu-types');
}
public function getPoolTypes() {
return $this->makeRequest('GET', '/catalog/pool-types');
}
public function createDesign($sessionId, $designConfig) {
$data = [
'sessionId' => $sessionId,
'designType' => $designConfig['type'],
'configuration' => $designConfig
];
return $this->makeRequest('POST', '/designs', $data);
}
public function calculatePricing($designId, $location) {
$data = [
'designId' => $designId,
'location' => $location
];
return $this->makeRequest('POST', '/pricing/calculate', $data);
}
public function generateQuote($designId, $customerInfo) {
$data = [
'designId' => $designId,
'customerInfo' => $customerInfo
];
return $this->makeRequest('POST', '/quotes/generate', $data);
}
}
// Usage example
try {
$api = new VisualizerAPI('your-api-key', 'your-user-id', 'your-business-id');
// Create session
$session = $api->createSession('photo-file-id');
echo "Session created: " . $session['id'] . "\n";
// Get ADU types
$aduTypes = $api->getADUTypes();
echo "Available ADU types: " . count($aduTypes) . "\n";
// Create design
$designConfig = [
'type' => 'adu',
'size' => '600_sqft',
'materials' => [
'exterior' => 'fiber_cement',
'roofing' => 'asphalt_shingle'
]
];
$design = $api->createDesign($session['id'], $designConfig);
echo "Design created: " . $design['id'] . "\n";
// Calculate pricing
$location = [
'zipCode' => '90210',
'state' => 'CA'
];
$pricing = $api->calculatePricing($design['id'], $location);
echo "Total cost: $" . number_format($pricing['totalCost'], 2) . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
WordPress Integration
'POST',
'callback' => 'handle_create_session',
'permission_callback' => '__return_true'
]);
register_rest_route('visualizer/v1', '/catalog/(?P
[a-zA-Z]+)', [
'methods' => 'GET',
'callback' => 'handle_get_catalog',
'permission_callback' => '__return_true'
]);
}
add_action('rest_api_init', 'visualizer_api_endpoint');
function handle_create_session(WP_REST_Request $request) {
$api_key = get_option('visualizer_api_key');
$user_id = get_option('visualizer_user_id');
$business_id = get_option('visualizer_business_id');
if (!$api_key || !$user_id || !$business_id) {
return new WP_Error('missing_credentials', 'API credentials not configured', ['status' => 500]);
}
$api = new VisualizerAPI($api_key, $user_id, $business_id);
try {
$file_id = $request->get_param('fileId');
$session = $api->createSession($file_id);
return rest_ensure_response([
'success' => true,
'sessionId' => $session['id']
]);
} catch (Exception $e) {
return new WP_Error('api_error', $e->getMessage(), ['status' => 500]);
}
}
function handle_get_catalog(WP_REST_Request $request) {
$api_key = get_option('visualizer_api_key');
$user_id = get_option('visualizer_user_id');
$business_id = get_option('visualizer_business_id');
$api = new VisualizerAPI($api_key, $user_id, $business_id);
try {
$type = $request->get_param('type');
if ($type === 'adu') {
$catalog = $api->getADUTypes();
} elseif ($type === 'pool') {
$catalog = $api->getPoolTypes();
} else {
return new WP_Error('invalid_type', 'Invalid catalog type', ['status' => 400]);
}
return rest_ensure_response($catalog);
} catch (Exception $e) {
return new WP_Error('api_error', $e->getMessage(), ['status' => 500]);
}
}
// Shortcode for embedding visualizer
function visualizer_shortcode($atts) {
$atts = shortcode_atts([
'type' => 'adu_pool',
'width' => '100%',
'height' => '600px'
], $atts);
return '
';
}
add_shortcode('visualizer', 'visualizer_shortcode');
?>
cURL Examples
Create Visualization Session
curl -X POST https://visualizer-api.serviceflow-pro.com/api/v1/visualizer/sessions \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id" \
-H "Content-Type: application/json" \
-d '{
"fileId": "existing-photo-file-id",
"sessionType": "adu_pool",
"description": "Backyard analysis for ADU and pool"
}'
Get Available ADU Types
curl -X GET https://visualizer-api.serviceflow-pro.com/api/v1/catalog/adu-types \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id"
Create Design Configuration
curl -X POST https://visualizer-api.serviceflow-pro.com/api/v1/designs \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id" \
-H "Content-Type: application/json" \
-d '{
"sessionId": "session-id-from-previous-call",
"designType": "adu",
"configuration": {
"type": "studio",
"size": "600_sqft",
"materials": {
"exterior": "fiber_cement",
"roofing": "asphalt_shingle",
"siding": "vinyl"
},
"features": ["deck", "storage", "parking"],
"placement": {
"x": 10,
"y": 15,
"rotation": 0
}
}
}'
Calculate Pricing
curl -X POST https://visualizer-api.serviceflow-pro.com/api/v1/pricing/calculate \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id" \
-H "Content-Type: application/json" \
-d '{
"designId": "design-id-from-previous-call",
"location": {
"zipCode": "90210",
"state": "CA",
"city": "Beverly Hills"
},
"options": {
"includeLaborCosts": true,
"includePermitCosts": true,
"includeEquipmentRental": true
}
}'
Generate Professional Quote
curl -X POST https://visualizer-api.serviceflow-pro.com/api/v1/quotes/generate \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id" \
-H "Content-Type: application/json" \
-d '{
"designId": "design-id-from-previous-call",
"customerInfo": {
"name": "John Smith",
"email": "john@example.com",
"phone": "+1-555-123-4567",
"address": {
"street": "123 Main St",
"city": "Beverly Hills",
"state": "CA",
"zipCode": "90210"
}
},
"quoteOptions": {
"includeTimeline": true,
"includeWarranty": true,
"includeFinancing": true,
"validityDays": 30
}
}'
Get Session Status
curl -X GET https://visualizer-api.serviceflow-pro.com/api/v1/visualizer/sessions/session-id \
-H "X-API-Key: your-api-key" \
-H "X-User-ID: your-user-id" \
-H "X-Business-ID: your-business-id"
Error Handling
Best Practices: Always implement proper error handling and retry logic for production applications.
Common Error Responses
{
"error": {
"code": "AUTHENTICATION_ERROR",
"message": "Invalid API key",
"details": "The provided API key is not valid or has expired"
}
}
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"details": "You have exceeded the rate limit of 100 requests per 15 minutes",
"retryAfter": 900
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request data",
"details": {
"fileId": "File ID is required",
"sessionType": "Must be one of: adu, pool, adu_pool"
}
}
}
Error Handling Example
async function handleAPICall(apiFunction) {
try {
const result = await apiFunction();
return { success: true, data: result };
} catch (error) {
if (error.response) {
const { status, data } = error.response;
switch (status) {
case 401:
console.error('Authentication failed:', data.error.message);
// Refresh API key or redirect to login
break;
case 429:
console.error('Rate limit exceeded, retrying in', data.error.retryAfter, 'seconds');
// Implement exponential backoff
setTimeout(() => handleAPICall(apiFunction), data.error.retryAfter * 1000);
break;
case 400:
console.error('Validation error:', data.error.details);
// Show user-friendly error messages
break;
default:
console.error('API error:', data.error.message);
}
} else {
console.error('Network error:', error.message);
}
return { success: false, error: error.message };
}
}
Testing & Development
Development Mode: Use the development bypass header for testing: X-Dev-Bypass: true
Test API Key Request
# Test your API connection
curl -X GET https://visualizer-api.serviceflow-pro.com/api/v1/health \
-H "X-API-Key: your-api-key"
Mock Data for Testing
{
"testFileId": "test-photo-12345",
"testSessionId": "session-67890",
"testDesignId": "design-abcdef",
"sampleADUConfig": {
"type": "studio",
"size": "600_sqft",
"materials": {
"exterior": "fiber_cement",
"roofing": "asphalt_shingle"
},
"features": ["deck", "storage"]
},
"sampleLocation": {
"zipCode": "90210",
"state": "CA"
}
}