Skip to main content
PUT
/
v1
/
trips
/
{trip_id}
/
metadata
Update Trip Metadata
curl --request PUT \
  --url https://api.bookovia.com/v1/trips/{trip_id}/metadata \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: <api-key>' \
  --data '
{
  "metadata": {
    "purpose": "<string>",
    "route_name": "<string>",
    "customer_id": "<string>",
    "work_order_id": "<string>",
    "priority": "<string>",
    "driver_notes": "<string>",
    "tags": [
      {}
    ],
    "cost_center": "<string>",
    "external_id": "<string>"
  },
  "replace_metadata": true
}
'
{
  "error": {
    "code": "trip_not_found",
    "message": "The specified trip_id was not found",
    "details": "Trip 'trip_1234567890abcdef' does not exist or is not associated with your organization"
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.bookovia.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Update Trip Metadata endpoint allows you to modify custom metadata, tags, and properties associated with a trip. This is useful for adding context, updating trip purposes, or correcting information after trip completion.
Metadata updates are allowed for both active and completed trips. Some fields may have restrictions based on trip status.

Authentication

This endpoint requires authentication via API key in the X-API-Key header. Required permissions: trips:write

Request

trip_id
string
required
Unique identifier for the trip to update
metadata
object
Custom metadata object to merge with existing metadata. Use null values to remove fields.
replace_metadata
boolean
default:"false"
If true, completely replace existing metadata instead of merging. Use with caution.

Request Example

curl -X PUT https://api.bookovia.com/v1/trips/trip_1234567890abcdef/metadata \
  -H "X-API-Key: bkv_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "metadata": {
      "purpose": "service",
      "customer_id": "CUST_ABC123",
      "work_order_id": "WO_789456",
      "priority": "urgent",
      "driver_notes": "Customer requested early arrival",
      "tags": ["hvac", "emergency", "residential"],
      "cost_center": "MAINTENANCE_DEPT",
      "billing_code": "EMRG_SVC_2024",
      "estimated_revenue": 350.00,
      "completion_status": "successful"
    }
  }'

Response

trip_id
string
Unique identifier for the updated trip
metadata
object
Complete updated metadata object after the merge/replacement
updated_at
string
ISO 8601 timestamp when the metadata was last updated
metadata_history
array
Array of metadata change records (if audit logging is enabled)

Success Response

{
  "trip_id": "trip_1234567890abcdef",
  "metadata": {
    "purpose": "service",
    "route_name": "Downtown Route A",
    "customer_id": "CUST_ABC123",
    "work_order_id": "WO_789456",
    "priority": "urgent",
    "driver_notes": "Customer requested early arrival",
    "tags": ["hvac", "emergency", "residential"],
    "cost_center": "MAINTENANCE_DEPT",
    "billing_code": "EMRG_SVC_2024",
    "estimated_revenue": 350.00,
    "completion_status": "successful",
    "created_by": "api_key_abc123",
    "created_at": "2024-04-13T10:30:00Z",
    "updated_by": "api_key_def456",
    "updated_at": "2024-04-13T15:45:00Z"
  },
  "updated_at": "2024-04-13T15:45:00Z",
  "metadata_history": [
    {
      "timestamp": "2024-04-13T15:45:00Z",
      "changed_by": "api_key_def456",
      "changes": {
        "added": ["work_order_id", "driver_notes", "completion_status"],
        "modified": ["priority", "customer_id"],
        "removed": []
      }
    }
  ]
}

Error Responses

{
  "error": {
    "code": "trip_not_found",
    "message": "The specified trip_id was not found",
    "details": "Trip 'trip_1234567890abcdef' does not exist or is not associated with your organization"
  }
}

SDK Examples

import Bookovia from '@bookovia/javascript-sdk';

const client = new Bookovia('bkv_test_your_api_key');

// Update service trip details
const updatedTrip = await client.trips.updateMetadata('trip_1234567890abcdef', {
  purpose: 'service',
  workOrderId: 'WO_789456',
  customerId: 'CUST_ABC123',
  priority: 'urgent',
  tags: ['hvac', 'emergency'],
  driverNotes: 'Customer requested early arrival'
});

// Add billing information after completion
await client.trips.updateMetadata('trip_1234567890abcdef', {
  billingCode: 'EMRG_SVC_2024',
  estimatedRevenue: 350.00,
  completionStatus: 'successful',
  invoiceGenerated: true
});

// Remove sensitive customer data (GDPR compliance)
await client.trips.updateMetadata('trip_1234567890abcdef', {
  customerId: null,
  customerName: null,
  customerPhone: null
});

console.log(`Trip metadata updated: ${updatedTrip.tripId}`);

Use Cases

Service Management Integration

// Update trip with service completion details
const completeServiceTrip = async (tripId, serviceDetails) => {
  await client.trips.updateMetadata(tripId, {
    completionStatus: 'completed',
    serviceCompletedAt: new Date().toISOString(),
    workPerformed: serviceDetails.workDescription,
    partsUsed: serviceDetails.parts,
    laborHours: serviceDetails.laborTime,
    customerSatisfaction: serviceDetails.rating,
    followUpRequired: serviceDetails.needsFollowUp,
    invoiceNumber: serviceDetails.invoiceId,
    totalCost: serviceDetails.totalAmount,
    paymentStatus: 'pending'
  });
  
  // Trigger invoice generation
  await generateInvoice(tripId, serviceDetails);
};

Delivery Management

# Track package delivery progress
async def update_delivery_status(trip_id, status, details):
    metadata_updates = {
        'delivery_status': status,
        'status_updated_at': datetime.utcnow().isoformat() + 'Z'
    }
    
    if status == 'delivered':
        metadata_updates.update({
            'delivered_at': details.get('delivered_at'),
            'signature_obtained': details.get('signature_obtained'),
            'delivery_notes': details.get('notes'),
            'delivery_photo_url': details.get('photo_url'),
            'recipient_name': details.get('recipient')
        })
    elif status == 'failed':
        metadata_updates.update({
            'failure_reason': details.get('reason'),
            'retry_scheduled': details.get('retry_date'),
            'customer_contacted': details.get('contacted')
        })
    
    await client.trips.update_metadata(
        trip_id=trip_id,
        metadata=metadata_updates
    )

Fleet Cost Tracking

// Update trip with cost and billing information
func updateTripCosts(tripID string, costs TripCosts) error {
    _, err := client.Trips.UpdateMetadata(context.Background(), tripID, &bookovia.UpdateMetadataRequest{
        Metadata: map[string]interface{}{
            "fuel_cost":           costs.FuelCost,
            "tolls_cost":          costs.TollsCost,
            "parking_cost":        costs.ParkingCost,
            "maintenance_cost":    costs.MaintenanceCost,
            "driver_wages":        costs.DriverWages,
            "total_trip_cost":     costs.TotalCost,
            "cost_per_km":         costs.TotalCost / costs.DistanceKm,
            "billing_rate":        costs.BillingRate,
            "revenue":            costs.Revenue,
            "profit_margin":      (costs.Revenue - costs.TotalCost) / costs.Revenue * 100,
            "cost_center":        costs.CostCenter,
            "project_code":       costs.ProjectCode,
            "approved_by":        costs.ApprovedBy,
            "expense_report_id":  costs.ExpenseReportID,
        },
    })
    
    return err
}

Best Practices

Metadata Schema Design

  • Use snake_case for field names consistently
  • Establish organization-wide metadata schemas
  • Document expected fields and data types
  • Use consistent enumeration values
const validateMetadata = (metadata) => {
  const schema = {
    purpose: ['delivery', 'service', 'personal', 'commute'],
    priority: ['low', 'normal', 'high', 'urgent'],
    tags: (value) => Array.isArray(value) && value.every(t => typeof t === 'string')
  };
  
  // Validate against schema
  for (const [field, validator] of Object.entries(schema)) {
    if (metadata[field] && !validator.includes?.(metadata[field])) {
      throw new Error(`Invalid ${field}: ${metadata[field]}`);
    }
  }
};

Performance Optimization

  • Group related metadata updates into single calls
  • Avoid frequent small updates during active trips
  • Use bulk operations for historical data updates
  • Keep metadata objects under 64KB
  • Store large documents externally and reference by URL
  • Use arrays efficiently for tags and categories

Next Steps

Get Trip Details

View updated trip information and metadata

List Trips

Search trips by metadata fields and values

Trip Analytics

Generate reports using metadata for segmentation

Fleet Management

Analyze fleet performance using trip metadata