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:
- Convert data types - Transform API responses to native types (
time.Timein Go,Datein TypeScript) - Provide type safety - Catch errors at compile time with strongly-typed responses
- Handle optional fields - Use language-appropriate patterns (pointers in Go, optional properties in TypeScript)
- Simplify access - Access response data directly without manual parsing
Type Conversion Examples
- Go
- TypeScript
// 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
// Upload a file
const response = await client.files.upload({
content: fileData,
filename: "damage-photo.jpg",
purpose: "crash_analysis"
});
// Wrapper converts API response to TypeScript types
const fileId: string = response.fileId;
const filename: string = response.filename;
const uploadTime: Date = response.uploadedAt; // Date object (not a string!)
const size: number = response.size;
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:
- Go
- TypeScript
// 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"),
}
// Optional fields use optional properties
interface FileInfo {
filename: string; // Required field
size?: number; // Optional field
description?: string; // Optional field
}
// Check and access optional fields
const info = response.fileInfo;
if (info.size !== undefined) {
console.log(`File size: ${info.size} bytes`);
}
// Optional fields in requests
const uploadRequest = {
content: fileData,
filename: "file.jpg",
description: "Vehicle damage photo" // Optional
};
Nested Objects and Arrays
Wrappers also handle complex nested structures:
- Go
- TypeScript
// 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)
}
// Get accident reconstruction results
const response = await client.crashAnalysis.getResults(caseId);
// Access nested objects
const deltaV: number = response.results.deltaV;
const principalDirection: number = response.results.pdof;
// Iterate over arrays
response.results.vehicles.forEach(vehicle => {
console.log(`Vehicle: ${vehicle.year} ${vehicle.make} ${vehicle.model}`);
});
Error Handling
Wrappers also provide structured error information:
- Go
- TypeScript
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")
}
}
try {
const response = await client.files.upload(uploadRequest);
} catch (error) {
// Wrapper provides structured error
console.error('Error:', error.message);
console.error('Code:', error.code);
// Check error types with helper functions
if (isValidationError(error)) {
console.log("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
- Use Type Safety - Leverage SDK type definitions to catch errors early
- Check Optional Fields - Always verify optional fields exist before accessing
- Let Wrappers Work - Don't try to parse raw responses; use the SDK types
- 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.