Skip to main content

Generating a Report

This guide walks you through generating a PDF technical report from vehicle damage photos. By the end, you'll have a downloadable report with Delta-V calculations, damage analysis, and crash dynamics.

What You'll Build

The technical report workflow creates a professional PDF document:

StepActionDescription
1Create CaseOrganize files under a case
2Upload PhotosUpload vehicle damage images
3Create ReportSubmit vehicle details for analysis
4Poll for CompletionMonitor progress (2-5 min)
5Download PDFGet the completed report

What You Need

Required:

  • At least one vehicle damage photo (JPEG or PNG)

Optional (but recommended):

  • Multiple angles: front, rear, sides, close-ups of damage
  • Vehicle information (make, model, year)
  • Accident details (date, description, location)
  • Defendant vehicle photos (for two-vehicle crashes)

Step 1: Create a Case

First, create a case to organize your files and reports:

package main

import (
"context"
"fmt"
"log"
"os"

silentwitness "github.com/silentwitness/sw-go-sdk"
)

func main() {
// Create client
client := silentwitness.NewClient(silentwitness.Config{
APIKey: os.Getenv("SW_API_KEY"),
})
defer client.Close()

ctx := context.Background()

// Create a case
caseResp, err := client.CreateCase(ctx, &silentwitness.CaseParams{
Name: silentwitness.String("Smith v. Johnson"),
ClientName: silentwitness.String("Jane Smith"),
})
if err != nil {
log.Fatalf("Failed to create case: %v", err)
}

fmt.Printf("Created case: %s\n", caseResp.ID)
}

Step 2: Upload Vehicle Photos

Upload the vehicle damage photos. Use the purpose field to indicate which vehicle the photos belong to:

// Load the photo
photoData, err := os.ReadFile("vehicle-damage-front.jpg")
if err != nil {
log.Fatalf("Failed to read photo: %v", err)
}

// Upload it
upload, err := client.UploadFile(ctx, &silentwitness.UploadFileParams{
CaseID: caseResp.ID,
Filename: "vehicle-damage-front.jpg",
Content: photoData,
Purpose: silentwitness.FilePurposeCrashPlaintiff,
})
if err != nil {
log.Fatalf("Upload failed: %v", err)
}

fmt.Printf("Uploaded file: %s\n", upload.FileID)

Purpose Values

PurposeDescription
crash_analysis_plaintiffPhotos of the plaintiff's vehicle
crash_analysis_defendantPhotos of the defendant's vehicle
More Photos = Better Analysis

Upload 4-8 photos per vehicle for best results. Include:

  • Front, rear, and side views
  • Close-ups of damage areas
  • Interior damage if applicable

Step 3: Create the Report

Submit the vehicle details and photo references to generate the report. The API will use ML to compute Delta-V, PDOF, and impact type from your photos.

response, err := client.CreateReport(ctx, &silentwitness.CreateReportParams{
CaseID: caseResp.ID,
Type: silentwitness.ReportTypeTechnicalReport,
Plaintiff: &silentwitness.VehicleDataParams{
ImageFileIds: []string{upload.FileID},
VehicleMaker: silentwitness.String("Toyota"),
VehicleModel: silentwitness.String("Camry"),
VehicleYear: silentwitness.String("2020"),
VehicleType: silentwitness.String("sedan"),
// Seatbelt/airbag data is per-occupant - see occupants field
},
AccidentDescription: silentwitness.String("Rear-end collision at intersection"),
AccidentDate: silentwitness.String("2024-03-15"),
})
if err != nil {
log.Fatalf("Report creation failed: %v", err)
}

fmt.Printf("Report created: %s\n", response.ReportID)

Required vs Optional Fields

Required:

  • caseId - The case to associate the report with
  • type - The report type (technical_report)
  • plaintiff.imageFileIds - At least one uploaded photo ID (or edrFileId)

Optional:

  • plaintiff.vehicleMaker, vehicleModel, vehicleYear, vehicleType
  • defendant - Second vehicle data for two-vehicle crashes
  • accidentDescription, accidentDate, accidentTime, accidentLocation
  • occupants - For integrated biomechanics analysis (includes per-occupant seatbeltWorn and airbagDeployed fields)

Step 4: Poll for Completion

Report generation takes 2-5 minutes. Poll the status every 5 seconds:

import "time"

reportID := response.ReportID

for {
report, err := client.GetReport(ctx, reportID)
if err != nil {
log.Fatalf("Failed to check status: %v", err)
}

fmt.Printf("Status: %s\n", report.Status)

switch report.Status {
case silentwitness.ReportStatusCompleted:
fmt.Printf("Report ready: %s\n", *report.ReportURL)
return
case silentwitness.ReportStatusFailed:
log.Fatal("Report generation failed")
}

time.Sleep(5 * time.Second)
}

Status Values

StatusDescription
pendingQueued for processing
processingCurrently generating
completedReport ready at reportUrl
failedGeneration failed

What's in the Report

The completed PDF includes:

SectionContents
Delta-V AnalysisChange in velocity calculations (computed by ML)
PDOF AnalysisPrincipal Direction of Force (impact angle)
Impact ClassificationImpact type and collision type (computed from PDOF)
Damage AssessmentPhoto-based damage severity analysis
MethodologyExplanation of analysis approach

Complete Code Example

Here's the full code putting it all together:

package main

import (
"context"
"fmt"
"log"
"os"
"time"

silentwitness "github.com/silentwitness/sw-go-sdk"
)

func main() {
// Create client
client := silentwitness.NewClient(silentwitness.Config{
APIKey: os.Getenv("SW_API_KEY"),
})
defer client.Close()

ctx := context.Background()

// Step 1: Create a case
caseResp, err := client.CreateCase(ctx, &silentwitness.CaseParams{
Name: silentwitness.String("Smith v. Johnson"),
ClientName: silentwitness.String("Jane Smith"),
})
if err != nil {
log.Fatalf("Failed to create case: %v", err)
}
fmt.Printf("Created case: %s\n", caseResp.ID)

// Step 2: Upload vehicle photos
photoData, err := os.ReadFile("vehicle-damage-front.jpg")
if err != nil {
log.Fatalf("Failed to read photo: %v", err)
}

upload, err := client.UploadFile(ctx, &silentwitness.UploadFileParams{
CaseID: caseResp.ID,
Filename: "vehicle-damage-front.jpg",
Content: photoData,
Purpose: silentwitness.FilePurposeCrashPlaintiff,
})
if err != nil {
log.Fatalf("Upload failed: %v", err)
}
fmt.Printf("Uploaded file: %s\n", upload.FileID)

// Step 3: Create technical report
response, err := client.CreateReport(ctx, &silentwitness.CreateReportParams{
CaseID: caseResp.ID,
Type: silentwitness.ReportTypeTechnicalReport,
Plaintiff: &silentwitness.VehicleDataParams{
ImageFileIds: []string{upload.FileID},
VehicleMaker: silentwitness.String("Toyota"),
VehicleModel: silentwitness.String("Camry"),
VehicleYear: silentwitness.String("2020"),
VehicleType: silentwitness.String("sedan"),
},
AccidentDescription: silentwitness.String("Rear-end collision at intersection"),
AccidentDate: silentwitness.String("2024-03-15"),
})
if err != nil {
log.Fatalf("Report creation failed: %v", err)
}
fmt.Printf("Report created: %s\n", response.ReportID)

// Step 4: Poll for completion
reportID := response.ReportID
for {
report, err := client.GetReport(ctx, reportID)
if err != nil {
log.Fatalf("Failed to check status: %v", err)
}

fmt.Printf("Status: %s\n", report.Status)

if report.Status == silentwitness.ReportStatusCompleted {
fmt.Printf("Report ready: %s\n", *report.ReportURL)
break
} else if report.Status == silentwitness.ReportStatusFailed {
log.Fatal("Report generation failed")
}

time.Sleep(5 * time.Second)
}
}

Troubleshooting

File Upload Issues

  • Maximum file size: 50MB per file
  • Supported formats: JPEG, PNG
  • Ensure the case exists before uploading files

Report Creation Issues

  • At least one plaintiff photo (or EDR file) is required
  • Vehicle year must be 4 digits (e.g., "2020")
  • Date format: YYYY-MM-DD (e.g., "2024-03-15")

Polling Tips

  • Poll every 3-5 seconds
  • Reports typically complete in 2-5 minutes
  • Implement exponential backoff for production use

Next Steps