Track Trip
Record complete asset journeys with route tracking, planned stops, and comprehensive trip analytics.
Overview
Trips track complete journeys from start to finish, recording the full GPS trace, planned stops, and metadata. Trip summaries provide analytics including distance, duration, and location count. A trip may represent a delivery, a pickup or something else.
Use Case
A delivery company needs to:
- Record delivery routes with start/end times
- Track planned stops at customer locations
- Analyze trip performance (distance, duration, efficiency)
- Store trip metadata (driver, packages, shift)
Trip Lifecycle
*Updates optional during active trip
Example 1: Start a Delivery Trip
Initiate a trip with planned stops and metadata.
- cURL
- JavaScript
curl -X POST https://api.magiclane.net/api/v1/start_trip \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"p_trip_id": "delivery_trip_001",
"p_asset_id": "vehicle_101",
"p_name": "Downtown Delivery Route",
"p_description": "Morning delivery run covering downtown area",
"p_meta_data": {
"shift": "morning",
"route_type": "delivery",
"priority": "high"
},
"p_attributes": {
"driver_name": "John Smith",
"estimated_duration_minutes": 120,
"package_count": 15,
"start_location": "Main Warehouse"
},
"p_stops": [
{
"name": "Main Warehouse",
"meta_data": {
"stop_type": "pickup",
"entry_point": "loading_dock_3",
"arrival_time": "08:00"
},
"geofence_id": "warehouse_safety_perimeter"
},
{
"name": "Downtown Office Building A",
"meta_data": {
"stop_type": "delivery",
"packages": 5,
"entry_point": "main_entrance"
},
"geofence_id": "downtown_delivery_zone"
},
{
"name": "Downtown Office Building B",
"meta_data": {
"stop_type": "delivery",
"packages": 10,
"entry_point": "side_entrance"
},
"geofence_id": "downtown_delivery_zone"
}
]
}'
const startTrip = async (assetId, tripData) => {
const response = await fetch(
'https://api.magiclane.net/api/v1/start_trip',
{
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: `delivery_trip_${Date.now()}`,
p_asset_id: assetId,
p_name: tripData.name,
p_description: tripData.description,
p_meta_data: {
shift: tripData.shift,
route_type: 'delivery',
priority: tripData.priority
},
p_attributes: {
driver_name: tripData.driverName,
estimated_duration_minutes: tripData.estimatedDuration,
package_count: tripData.packageCount
},
p_stops: tripData.stops.map(stop => ({
name: stop.name,
meta_data: {
stop_type: stop.type,
packages: stop.packages
},
geofence_id: stop.geofenceId
}))
})
}
);
const result = await response.json();
console.log(`Trip started: ${result.trip_id}`);
return result;
};
// Example usage
startTrip('vehicle_101', {
name: 'Downtown Delivery Route',
description: 'Morning delivery run',
shift: 'morning',
priority: 'high',
driverName: 'John Smith',
estimatedDuration: 120,
packageCount: 15,
stops: [
{
name: 'Main Warehouse',
type: 'pickup',
geofenceId: 'warehouse_safety_perimeter'
},
{
name: 'Office Building A',
type: 'delivery',
packages: 5,
geofenceId: 'downtown_delivery_zone'
}
]
});
Response (code 200 OK)
{
"trip_id": "delivery_trip_001",
"error": ""
}
Example 2: Get Trip Information
Retrieve current trip details including route progress. Works for both active and ended trips.
- cURL
- JavaScript
curl -X GET https://api.magiclane.net/api/v1/get_trip_by_id \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"p_trip_id": "delivery_trip_001"
}'
const getTripInfo = async (tripId) => {
const response = await fetch(
'https://api.magiclane.net/api/v1/get_trip_by_id',
{
method: 'GET',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
}
);
const result = await response.json();
// Display trip status
console.log(`Trip: ${result.data.trip.name}`);
console.log(`State: ${result.data.trip.state}`);
console.log(`Route points: ${result.data.trip.route.length}`);
return result;
};
// Usage
await getTripInfo('delivery_trip_001');
Response for Active Trip (code 200 OK)
{
"status": "Ok",
"data": {
"trip": {
"id": "delivery_trip_001",
"asset_id": "vehicle_101",
"state": "active",
"name": "Downtown Delivery Route",
"description": "Morning delivery run covering downtown area",
"meta_data": {
"shift": "morning",
"priority": "high",
"route_type": "delivery"
},
"attributes": {
"driver_name": "John Smith",
"package_count": 15,
"start_location": "Main Warehouse",
"estimated_duration_minutes": 120
},
"started_at": 1767863673,
"ended_at": null,
"created_at": 1767863673,
"updated_at": 1767863673,
"stops": [
{
"name": "Main Warehouse",
"meta_data": {
"stop_type": "pickup",
"entry_point": "loading_dock_3",
"arrival_time": "08:00"
},
"geofence_id": "warehouse_safety_perimeter"
},
{
"name": "Downtown Office Building A",
"meta_data": {
"packages": 5,
"stop_type": "delivery",
"entry_point": "main_entrance"
},
"geofence_id": "downtown_delivery_zone"
},
{
"name": "Downtown Office Building B",
"meta_data": {
"packages": 10,
"stop_type": "delivery",
"entry_point": "side_entrance"
},
"geofence_id": "downtown_delivery_zone"
}
],
"route": [
{
"accuracy": 0.5,
"altitude": null,
"bearing": 45,
"location": {
"lat": 45.6485790625,
"lon": 25.6140759375
},
"meta_data": null,
"speed": 18,
"timestamp": 1767864327
},
{
"accuracy": 0.5,
"altitude": null,
"bearing": 50,
"location": {
"lat": 45.649011875,
"lon": 25.614433125
},
"meta_data": null,
"speed": 20,
"timestamp": 1767864810
}
]
}
}
}
Use Cases:
- Real-time monitoring: Track trip progress while in motion
- Route replay: Visualize the path taken
- Status checks: Verify trip state and current location
- Debugging: Investigate trip issues or verify data
Key Differences:
- Active trips:
ended_atisnull, route still growing andstateis set toactive - Ended trips:
ended_athas timestamp, route complete,stateis set toended
Example 3: Update Trip During Journey
Update trip metadata while the trip is active.
- cURL
- JavaScript
curl -X POST https://api.magiclane.net/api/v1/update_trip \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"p_trip_id": "delivery_trip_001",
"p_asset_id": "vehicle_101",
"p_meta_data": {
"shift": "morning",
"route_type": "delivery",
"priority": "high",
"status": "delayed",
"delay_reason": "traffic_accident",
"estimated_delay_minutes": 30
},
"p_attributes": {
"driver_name": "John Smith",
"estimated_duration_minutes": 150,
"package_count": 15,
"current_location": "Highway Exit 42",
"completed_stops": 1
}
}'
const updateTrip = async (tripId, updates) => {
const response = await fetch(
'https://api.magiclane.net/api/v1/update_trip',
{
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId,
p_asset_id: updates.assetId,
p_meta_data: {
...updates.metaData,
last_updated: new Date().toISOString()
},
p_attributes: updates.attributes
})
}
);
return response.json();
};
// Example: Update trip with delay
updateTrip('delivery_trip_001', {
assetId: 'vehicle_101',
metaData: {
status: 'delayed',
delay_reason: 'traffic_accident',
estimated_delay_minutes: 30
},
attributes: {
current_stop: 2,
completed_deliveries: 5
}
});
Important: Only active trips can be updated. Once ended, trips become read-only.
Response (code 200 OK)
{
"id": "delivery_trip_001",
"error": ""
}
Example 4: End Trip
Mark the trip as completed.
- cURL
- JavaScript
curl -X GET https://api.magiclane.net/api/v1/end_trip_by_id \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"p_trip_id": "delivery_trip_001"
}'
const endTrip = async (tripId) => {
const response = await fetch(
'https://api.magiclane.net/api/v1/end_trip_by_id',
{
method: 'GET',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
}
);
const result = await response.json();
console.log(`Trip ended: ${result.status}`);
return result;
};
Response (code 200 OK)
{
"status": "Ok"
}
Example 5: Get Trip Summary
Retrieve comprehensive analytics after trip completion.
- cURL
- JavaScript
curl -X GET https://api.magiclane.net/api/v1/get_trip_summary \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"p_trip_id": "delivery_trip_001"
}'
const getTripSummary = async (tripId) => {
const response = await fetch(
'https://api.magiclane.net/api/v1/get_trip_summary',
{
method: 'GET',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
}
);
const summary = await response.json();
// Calculate metrics
const avgSpeed = summary.data.trip.distance_m / summary.data.trip.duration_s;
const durationMinutes = summary.data.trip.duration_s / 60;
console.log(`Trip Summary:
Distance: ${(summary.data.trip.distance_m / 1000).toFixed(2)} km
Duration: ${durationMinutes.toFixed(0)} minutes
Avg Speed: ${(avgSpeed * 3.6).toFixed(1)} km/h
GPS Points: ${summary.data.trip.location_count}
`);
return summary;
};
Response Structure
{
"status": "Ok",
"data": {
"trip": {
"id": "delivery_trip_001",
"asset_id": "vehicle_101",
"state": "ended",
"name": "Downtown Delivery Route",
"distance_m": 8543.67,
"duration_s": 3420,
"location_count": 114,
"started_at": 1767863673,
"ended_at": 1767867093,
"route": [...],
"stops": [...],
"meta_data": {...},
"attributes": {...},
"asset": {
"id": "vehicle_101",
"name": "Delivery Van 101",
"properties": {...},
"latest_location": {...}
}
}
}
}
Complete Trip Workflow Example
- JavaScript
class TripManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.magiclane.net/api/v1';
}
async startTrip(assetId, tripConfig) {
const tripId = `trip_${Date.now()}`;
const response = await fetch(`${this.baseUrl}/start_trip`, {
method: 'POST',
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId,
p_asset_id: assetId,
p_name: tripConfig.name,
p_description: tripConfig.description,
p_meta_data: tripConfig.metaData,
p_attributes: tripConfig.attributes,
p_stops: tripConfig.stops
})
});
return response.json();
}
async getTripInfo(tripId) {
const response = await fetch(`${this.baseUrl}/get_trip_by_id`, {
method: 'GET',
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
});
return response.json();
}
async updateTripStatus(tripId, assetId, status) {
const response = await fetch(`${this.baseUrl}/update_trip`, {
method: 'POST',
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId,
p_asset_id: assetId,
p_meta_data: {
status: status,
updated_at: new Date().toISOString()
}
})
});
return response.json();
}
async endTrip(tripId) {
const response = await fetch(`${this.baseUrl}/end_trip_by_id`, {
method: 'GET',
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
});
return response.json();
}
async getTripAnalytics(tripId) {
const summary = await fetch(`${this.baseUrl}/get_trip_summary`, {
method: 'GET',
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
p_trip_id: tripId
})
}).then(r => r.json());
const trip = summary.data.trip;
return {
distance_km: (trip.distance_m / 1000).toFixed(2),
duration_minutes: Math.round(trip.duration_s / 60),
avg_speed_kmh: ((trip.distance_m / trip.duration_s) * 3.6).toFixed(1),
gps_points: trip.location_count,
stops_planned: trip.stops.length
};
}
}
// Usage
const manager = new TripManager('YOUR_API_KEY');
// Start trip
const trip = await manager.startTrip('vehicle_101', {
name: 'Morning Route',
description: 'Daily delivery run',
metaData: { shift: 'morning' },
attributes: { driver: 'John Smith' },
stops: [...]
});
// Monitor trip progress
const tripInfo = await manager.getTripInfo(trip.trip_id);
console.log(`Current state: ${tripInfo.data.trip.state}`);
console.log(`Route points: ${tripInfo.data.trip.route.length}`);
// Update during trip
await manager.updateTripStatus(trip.trip_id, 'vehicle_101', 'in_progress');
// End trip
await manager.endTrip(trip.trip_id);
// Get analytics
const analytics = await manager.getTripAnalytics(trip.trip_id);
console.log(analytics);
Trip States
| State | Description | Can Update | Can End | Summary Available | Get Info Available |
|---|---|---|---|---|---|
active | Trip in progress | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes |
ended | Trip completed | ❌ No | ❌ No | ✅ Yes | ✅ Yes |
Use Case Examples
Daily Route Tracking
const dailyRoute = {
name: `Route ${new Date().toLocaleDateString()}`,
metaData: {
shift: 'day',
route_number: 'R-42',
vehicle_type: 'van'
},
attributes: {
driver: 'Jane Doe',
start_odometer: 45820,
fuel_level: 85
}
};
Service Call Tracking
const serviceTrip = {
name: 'Service Call #1234',
metaData: {
service_type: 'maintenance',
priority: 'urgent',
customer_id: 'CUST-5678'
},
stops: [
{
name: 'Customer Site A',
meta_data: { service_duration_min: 45 },
geofence_id: 'customer_site_a'
}
]
};
Multi-Stop Delivery
const deliveryTrip = {
name: 'Express Delivery Run',
attributes: {
total_packages: 25,
delivery_count: 8,
pickup_count: 2
},
stops: stops.map((stop, index) => ({
name: stop.name,
meta_data: {
sequence: index + 1,
packages: stop.packageCount,
time_window: stop.timeWindow
},
geofence_id: stop.geofenceId
}))
};
Notes
- Use meta_data for flexible trip categorization
- Use
get_trip_by_idfor both active and ended trips - Use
get_trip_summaryonly for ended trips (includes analytics) - Trip info includes real-time route data as it's being recorded
- Updates only work on active trips
- Don't store sensitive data in trip metadata
- Store trip IDs for later retrieval and analysis