Skip to main content

Response Format

SDK Response Wrappers

The Silent Witness SDKs act as typed wrappers around the API, automatically converting protobuf responses to native language types. This means you work with familiar types like string, number, Date, and strongly-typed objects instead of raw API responses.

What Are Wrappers?

Wrappers are language-specific interfaces that:

  1. Convert data types - Transform API responses to native types (time.Time in Go, Date in TypeScript)
  2. Provide type safety - Catch errors at compile time with strongly-typed responses
  3. Handle optional fields - Use language-appropriate patterns (pointers in Go, optional properties in TypeScript)
  4. Simplify access - Access response data directly without manual parsing

Type Conversion Examples

// Upload a file
response, err := client.Files.Upload(ctx, &silentwitness.UploadFileRequest{
Content: fileBytes,
Filename: silentwitness.String("damage-photo.jpg"),
Purpose: silentwitness.String("crash_analysis"),
})
if err != nil {
log.Fatal(err)
}

// Wrapper converts API response to Go types
fileID := response.FileId // string
filename := response.Filename // string
uploadTime := response.UploadedAt // time.Time (not a string!)
size := response.Size // int64

Core Type Mappings

The SDK wrappers handle these conversions automatically:

  • Strings: API string fields → Native strings (string)
  • Numbers: API numeric fields → Native numbers (int64, float64, number)
  • Timestamps: API timestamps → Native datetime (time.Time, Date)
  • Booleans: API boolean fields → Native booleans (bool, boolean)

Optional Fields

Wrappers handle optional fields using language-specific patterns:

// Optional fields use pointers in Go
type FileInfo struct {
Filename string // Required field
Size *int64 // Optional field
Description *string // Optional field
}

// Check and access optional fields
info := response.FileInfo
if info.Size != nil {
fmt.Printf("File size: %d bytes", *info.Size)
}

// Helper functions for creating optional values
uploadRequest := &silentwitness.UploadFileRequest{
Content: fileBytes,
Filename: silentwitness.String("file.jpg"),
Description: silentwitness.String("Vehicle damage photo"),
}

Nested Objects and Arrays

Wrappers also handle complex nested structures:

// Get accident reconstruction results
response, err := client.CrashAnalysis.GetResults(ctx, caseId)
if err != nil {
log.Fatal(err)
}

// Access nested objects
deltaV := response.Results.DeltaV // float64
principalDirection := response.Results.PDOF // float64

// Iterate over arrays
for _, vehicle := range response.Results.Vehicles {
fmt.Printf("Vehicle: %s %s %s\n",
vehicle.Year, vehicle.Make, vehicle.Model)
}

Error Handling

Wrappers also provide structured error information:

response, err := client.Files.Upload(ctx, uploadRequest)
if err != nil {
// Wrapper provides structured error
fmt.Printf("Error: %v", err)

// Check error types with helper functions
if silentwitness.IsValidationError(err) {
fmt.Println("Check your request parameters")
}
}

Benefits of SDK Wrappers

  • Type Safety: Catch errors at compile time with strongly-typed responses
  • Native Types: Work with familiar language types, not raw API formats
  • No Parsing: No manual JSON parsing or type conversion needed

Best Practices

  1. Use Type Safety - Leverage SDK type definitions to catch errors early
  2. Check Optional Fields - Always verify optional fields exist before accessing
  3. Let Wrappers Work - Don't try to parse raw responses; use the SDK types
  4. Handle Errors - Use SDK error helpers for type-specific error handling
tip

The SDK wrappers handle all the complexity of API communication, type conversion, and error handling so you can focus on building your application.